LinkedList和二叉树和HashMap

LinkedList

  1. Java 1.8之前是双向循环链表
  2. Java 1.8之后是双向不循环链表
  3. 建议同学们自行实现一个 双向不循环链表,并且实现追加,插入,删除,遍历操作

二叉树

  1. 每个父节点只有两种子节点的树形数据结构
  2. 左子节点中存储的数据小于父节点数据,右子节点存储数据大于父节点数据
  3. 由于操作性能是2分查找性能,经常用于排序和查找
    二叉树添加元素: 递归添加元素,相同元素不添加,右侧添加小的,右侧添加大的
    二叉树遍历:
  4. 先序遍历: 输出顺序 中 左 右
  5. 中序遍历: 输出顺序 左 中 右 , 最常见遍历输出,输出结果是排序结果
  6. 后序遍历: 输出顺序 左 右 中
    案例:

/**
* 二叉树,由于元素需要比较大小,所有元素应该实现
* Comparable接口
* E extends Comparable 泛型E必须实现 Comparable
* 用于比较两个元素的大小
* @param
*/

public class Tree>{
		private Node root;
		private int size=0;
		private class Node{
			E data;
			Node parent;
			Node left;
			Node right;
			public Node(E e) {
				data = e;
			}
		

boolean addChild(E e) {
				//比较数据 
				//val == 0 则 e和data相等
				//val > 0   则 e大于data
				//val < 0  则 e小于data
				int val = e.compareTo(data);
				if(val==0) {
					return false;
				}
				if(val < 0) {
					//向左侧添加节点
					if(left==null) {
						left = new Node(e);
						//左侧新节点的父节点是当前节点
						left.parent = this; 
						size++;
						return true;
					} else {
						//如果左侧已经有节点了,就在左侧递归添加子节点
						return left.addChild(e);
					}
				}else {
					//向右侧添加节点
					if(right == null) {
						right=new Node(e);
						right.parent = this;
						size++;
						return true;
					}else {
						return right.addChild(e);
					}
				}
			}
		
		/**
		 * 中序遍历算法
		 */
		public void appendTo(StringBuilder buf) {
			//输出顺序是 左 中 右
			if(left!=null) {
				//将左侧数据添加到 buf
				left.appendTo(buf); 
			}
			//添加“中”数据, 就是当前的data
			buf.append(data).append(", "); 
			if(right!=null) {
				//将右侧数据添加到 buf
				right.appendTo(buf); 
			}
		}
		
	}
	public boolean add(E e) {
		if(root==null) {
			//第一次添加根节点
			root = new Node(e);
			size++;
			return true;
		} else {
			//Child 孩子 
			//为根元素添加子节点
			return root.addChild(e);
		}
	}
	
	/**
	 * 实现二叉树的中序遍历输出
	 */
	public String toString() {
		if(root==null) {
			return "[]"; 
		}
		StringBuilder buf = new StringBuilder("[");
		root.appendTo(buf); //递归算法,实现中序遍历
		//去除最后一个 逗号 
		int index = buf.lastIndexOf(",");
		buf.delete(index, buf.length());
		buf.append("]");
		return buf.toString();
	}
}

红黑树

自平衡二叉树,采用5个(平衡)规则:

  1. 每个节点不是红的就是黑的,每个节点的红黑可以转换
  2. 根元素是黑的。
  3. 所有null子节点,算黑的。
  4. 如果一个节点是红的,下一个一定是黑的
  5. 从一个节点开始,其子孙路径上是全部黑数量需要一致。
    如果不符合如上规则,就进行转置调整。直到满足5条规则为止。

关于集合框架

接口

Collecion
		|-- List
		|    |-- ArrayList
		|    |-- LinkedList
		|-- Set
			 |-- HashSet 内部是 HashMap,只使用key存储数据
			 |-- SortedSet //排序的
					|-- TreeSet 内部是 TreeMap,只使用key存储数据 
		 
Map	
 |-- HashMap 散列表算法
 |-- SortedMap
		|- TreeMap 红黑树--自平衡二叉树

HashMap 工作原理

  1. 散列表内部封装了散列数组,数组元素类型是 散列桶 节点来下
  2. 散列桶是一个链表结构
    1. (Java 8)如果链表节点数量超过8个元素,会转换为红黑树!
  3. 添加数据时候
    1. 先根据key的hashCode计算出 散列数组的下标位置,
    2. 再在散列桶中利用equals方法查找key
    3. 找到就替换,没有找到就插入
    4. 如果元素数量超过 散列数组容量的75%(加载因子),则对散列数组进行扩容(1倍)
    5. 扩容后,散列表会将元素进行“重新散列”
  4. 查找时候
    1. 先根据key的hashCode计算出 散列数组的下标位置,
    2. 再在散列桶中利用equals方法查找key
    3. 找到就返回value,没有找到返回null
      为啥快:
  5. 相对于顺序顺序查找,散列查找可以根据key快速定位到 散列桶位置,在散列桶中,元素较少,可以开始搜索到数据。
  6. Java 8 以后,在散列桶中元素较多时候,会组织成“红黑树”进一步提高散列桶中的查找效率。
    关于hashCode方法:
  7. hashCode() 是java设计者为 散列表 而设计方法。
  8. hashCode() 的默认值,不是对象的内存地址!Java8 中是稳定的随机数。每次调用都一样。
  9. Java编程建议:
    1. 在重写equals方法时候,要一起重写hashCode()
    2. 两个对象equals相等时候,其hashCode() 必须一样
    3. 两个对象equals不等时候,其hashCode() 尽可能不同

你可能感兴趣的:(java基础)