Java数据结构

Java数据结构,第1张

Java数据结构

文章目录
  • 前言情景引入
  • 一、哈希表是什么?
    • 1.实例+代码
  • 二、二叉树
    • 1.树的引入
    • 2.二叉树的遍历


前言情景引入

有一个公司,当有新的员工来报道时,要求将该员工的信息加入(id,性别,年龄,住址…),当输入该员工的id时,要求查找到该员工的所有信息.
要求:不使用数据库,尽量节省内存,速度越快越好=>哈希表(散列)

一、哈希表是什么?

散列表(Hashtable,也叫哈希表),是根据关键码值(Keyvalue)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

1.实例+代码

有一个公司,当有新的员工来报道时,要求将该员工的信息加入(id,性别,年龄,名字,住址…),当输入该员工的id时,要求查找到该员工的所有信息.

要求:
1)不使用数据库,,速度越快越好=>哈希表(散列)
2)添加时,保证按照id从低到高插入
3)使用链表来实现哈希表,该链表不带表头[即:链表的第一个结点就存放雇员信息]
package com.JavaTest.Demo;

import java.util.Scanner;

public class HashTabDemo {

	public static void main(String[] args) {
		
		//创建哈希表
		HashTab hashTab = new HashTab(7);
	
		String key = "";
		Scanner scanner = new Scanner(System.in);
		while(true) {
			System.out.println("add:  添加雇员");
			System.out.println("list: 显示雇员");
			System.out.println("find: 查找雇员");
			System.out.println("exit: 退出系统");
			
			key = scanner.next();
			switch (key) {
			case "add":
				System.out.println("输入id");
				int id = scanner.nextInt();
				System.out.println("输入名字");
				String name = scanner.next();
				
				Emp emp = new Emp(id, name);
				hashTab.add(emp);
				break;
			case "list":
				hashTab.list();
				break;
			case "find":
				System.out.println("请输入要查找的id");
				id = scanner.nextInt();
				hashTab.findEmpById(id);
				break;
			case "exit":
				scanner.close();
				System.exit(0);
			default:
				break;
			}
		}	
	}
}


class HashTab {
	private EmplinkedList[] emplinkedListArray;
	private int size; //表示链表
	
	public HashTab(int size) {
		this.size = size;
		emplinkedListArray = new EmplinkedList[size];
		for(int i = 0; i < size; i++) {
			emplinkedListArray[i] = new EmplinkedList();
		}
	}
	
	public void add(Emp emp) {
		int emplinkedListNO = hashFun(emp.id);
		emplinkedListArray[emplinkedListNO].add(emp);
		
	}
	//遍历
	public void list() {
		for(int i = 0; i < size; i++) {
			emplinkedListArray[i].list(i);
		}
	}
	
	//根据id,查找雇员
	public void findEmpById(int id) {
		int emplinkedListNO = hashFun(id);
		Emp emp = emplinkedListArray[emplinkedListNO].findEmpById(id);
		if(emp != null) {
			System.out.printf("在第%d条链表中找到 雇员 id = %dn", (emplinkedListNO + 1), id);
		}else{
			System.out.println("在哈希表中,没有找到该雇员");
		}
	}
	
	public int hashFun(int id) {
		return id % size;
	}
	
	
}
//表示一个雇员
class Emp {
	public int id;
	public String name;
	public Emp next; 
	public Emp(int id, String name) {
		super();
		this.id = id;
		this.name = name;
	}
}

class EmplinkedList {
	private Emp head; 
	public void add(Emp emp) {
		if(head == null) {
			head = emp;
			return;
		}
		
		Emp curEmp = head;
		while(true) {
			if(curEmp.next == null) {
				break;
			}
			curEmp = curEmp.next; 
		}
		curEmp.next = emp;
	}
	//遍历
	public void list(int no) {
		if(head == null) { 
			System.out.println("第 "+(no+1)+" 链表为空");
			return;
		}
		System.out.print("第 "+(no+1)+" 链表的信息为");
		Emp curEmp = head; //辅助指针
		while(true) {
			System.out.printf(" => id=%d name=%st", curEmp.id, curEmp.name);
			if(curEmp.next == null) {
				break;
			}
			curEmp = curEmp.next; //后移
		}
		System.out.println();
	}
	
	public Emp findEmpById(int id) {
		//判断链表是否为空
		if(head == null) {
			System.out.println("链表为空");
			return null;
		}
		//辅助指针
		Emp curEmp = head;
		while(true) {
			if(curEmp.id == id) {
				break;
			}
			if(curEmp.next == null) {
				curEmp = null;
				break;
			}
			curEmp = curEmp.next;		}
		return curEmp;
	}
	
}


二、二叉树 1.树的引入

1、数组存储方式的分析
优点:通过下标方式访问元素,速度快。对于有序数组,还可使用二分查找提高检索速度。
缺点:如果要检索具体某个值,或者插入值(按一定顺序)会整体移动,效率较低
2、链式存储方式的分析
优点:在一定程度上对数组存储方式有优化(比如:插入一个数值节点,只需要将插入节点,链接到链表中即可,删除效率也很好)。
缺点:在进行检索时,效率仍然较低,比如(检索某个值,需要从头节点开始遍历)
3、树存储方式的分析
能提高数据存储,读取的效率,比如利用二叉排序树(BinarySortTree),既可以保证数据的检索速度,同时也可以保证数据的插入,删除,修改的速度。

2.二叉树的遍历

思路:
1. 因为我们的二叉树是单向的,所以我们是判断当前结点的子结点是否需要删除结点,而不能去判断当前这个结点是不是需要删除结点.
2. 如果当前结点的左子结点不为空,并且左子结点 就是要删除结点,就将this.left = null; 并且就返回(结束递归删除)
3. 如果当前结点的右子结点不为空,并且右子结点 就是要删除结点,就将this.right= null ;并且就返回(结束递归删除)
4. 如果第2和第3步没有删除结点,那么我们就需要向左子树进行递归删除
5. 如果第4步也没有删除结点,则应当向右子树进行递归删除.
代码如下(示例):

package com.JavaTest.Demo;

public class BinaryTreeDemo {

	public static void main(String[] args) {
		BinaryTree binaryTree = new BinaryTree();
	
		HeroNode root = new HeroNode(1, "宋江");
		HeroNode node2 = new HeroNode(2, "吴用");
		HeroNode node3 = new HeroNode(3, "卢俊义");
		HeroNode node4 = new HeroNode(4, "林冲");
		HeroNode node5 = new HeroNode(5, "关胜");
		
		root.setLeft(node2);
		root.setRight(node3);
		node3.setRight(node4);
		node3.setLeft(node5);
		binaryTree.setRoot(root);
		

	    System.out.println("前序遍历"); 
		binaryTree.preOrder();
		
		System.out.println("中序遍历");
		binaryTree.infixOrder();	
		
		System.out.println("后序遍历");
		binaryTree.postOrder(); 
		
		
	
		
		
		System.out.println("后序遍历方式");
		HeroNode resNode = binaryTree.postOrderSearch(5);
		if (resNode != null) {
			System.out.printf("找到了,信息为 no=%d name=%s", resNode.getNo(), resNode.getName());
		} else {
			System.out.printf("没有找到 no = %d 的英雄", 5);
					}
		
		
		
	}
}

class BinaryTree {
	private HeroNode root;

	public void setRoot(HeroNode root) {
		this.root = root;
	}
	
	//前序遍历
	public void preOrder() {
		if(this.root != null) {
			this.root.preOrder();
		}else {
			System.out.println("二叉树为空,无法遍历");
		}
	}
	
	//中序遍历
	public void infixOrder() {
		if(this.root != null) {
			this.root.infixOrder();
		}else {
			System.out.println("二叉树为空,无法遍历");
		}
	}
	//后序遍历
	public void postOrder() {
		if(this.root != null) {
			this.root.postOrder();
		}else {
			System.out.println("二叉树为空,无法遍历");
		}
	}
	
	//前序遍历
	public HeroNode preOrderSearch(int no) {
		if(root != null) {
			return root.preOrderSearch(no);
		} else {
			return null;
		}
	}
	//中序遍历
	public HeroNode infixOrderSearch(int no) {
		if(root != null) {
			return root.infixOrderSearch(no);
		}else {
			return null;
		}
	}
	//后序遍历
	public HeroNode postOrderSearch(int no) {
		if(root != null) {
			return this.root.postOrderSearch(no);
		}else {
			return null;
		}
	}
}

class HeroNode {
	private int no;
	private String name;
	private HeroNode left; //默认null
	private HeroNode right; //默认null
	public HeroNode(int no, String name) {
		this.no = no;
		this.name = name;
	}
	public int getNo() {
		return no;
	}
	public void setNo(int no) {
		this.no = no;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public HeroNode getLeft() {
		return left;
	}
	public void setLeft(HeroNode left) {
		this.left = left;
	}
	public HeroNode getRight() {
		return right;
	}
	public void setRight(HeroNode right) {
		this.right = right;
	}
	
	public String toString() {
		return "Heronode [no=" + no + ", name=" + name + "]";
	}
	//编写前序遍历的方法
	public void preOrder() {
		System.out.println(this); 

		if(this.left != null) {
			this.left.preOrder();
		}
		if(this.right != null) {
			this.right.preOrder();
		}
	}
	//中序遍历
	public void infixOrder() {
		if(this.left != null) {
			this.left.infixOrder();
		}
		System.out.println(this);
		if(this.right != null) {
			this.right.infixOrder();
		}
	}
	//后序遍历
	public void postOrder() {
		if(this.left != null) {
			this.left.postOrder();
		}
		if(this.right != null) {
			this.right.postOrder();
		}
		System.out.println(this);
	}
	
	public HeroNode preOrderSearch(int no) {
		System.out.println("进入前序遍历");
		//比较当前结点是不是
		if(this.no == no) {
			return this;
		}
		//1.则判断当前结点的左子节点是否为空,如果不为空,则递归前序查找
		//2.如果左递归前序查找,找到结点,则返回
		HeroNode resNode = null;
		if(this.left != null) {
			resNode = this.left.preOrderSearch(no);
		}
		if(resNode != null) {
			return resNode;
		}
		//1.左递归前序查找,找到结点,则返回,否继续判断,
		//2.当前的结点的右子节点是否为空,如果不空,则继续向右递归前序查找
		if(this.right != null) {
			resNode = this.right.preOrderSearch(no);
		}
		return resNode;
	}
	
	//中序遍历查找
	public HeroNode infixOrderSearch(int no) {
		HeroNode resNode = null;
		if(this.left != null) {
			resNode = this.left.infixOrderSearch(no);
		}
		if(resNode != null) {
			return resNode;
		}
		System.out.println("进入中序查找");
		//如果找到,则返回,如果没有找到,就和当前结点比较,如果是则返回当前结点
		if(this.no == no) {
			return this;
		}
	
		if(this.right != null) {
			resNode = this.right.infixOrderSearch(no);
		}
		return resNode;
		
	}
	
	//后序遍历查找
	public HeroNode postOrderSearch(int no) {

		HeroNode resNode = null;
		if(this.left != null) {
			resNode = this.left.postOrderSearch(no);
		}
		if(resNode != null) {
			return resNode;
		}
	
		if(this.right != null) {
			resNode = this.right.postOrderSearch(no);
		}
		if(resNode != null) {
			return resNode;
		}
		System.out.println("进入后序查找");
		if(this.no == no) {
			return this;
		}
		return resNode;
	}
	
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/zaji/4969827.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-13
下一篇 2022-11-13

发表评论

登录后才能评论

评论列表(0条)

保存