算法习题之有序表

有序表

  • 搜索二叉树
  • 搜索二叉树查询key(查询某个key存在还是不存在)
  • 搜索二叉树插入新的key
  • 搜索二叉树删除key
  • 搜索二叉树特别不讲究
  • AVL树、SB树、红黑树的共性
  • AVL树、SB树、红黑树的不同
  • AVL树
  • AVL数

搜索二叉树

搜索二叉树一定要说明以什么标准来排序
经典的搜索二叉树,树上没有重复的用来排序的key值
如果有重复节点的需求,可以在一个节点内部增加数据项

搜索二叉树查询key(查询某个key存在还是不存在)

1)如果当前节点的value==key,返回true
2)如果当前节点的value 3)如果当前节点的value>key,当前节点向右移动
4)如果当前节点变成null,返回false

搜索二叉树插入新的key

和查询过程一样,但当前节点滑到空的时候,就插入在这里

搜索二叉树删除key

1)先找到key所在的节点
2)如果该节点没有左孩子、没有右孩子,直接删除即可
3)如果该节点有左孩子、没有右孩子,直接用左孩子顶替该节点
4)如果该节点没有左孩子、有右孩子,直接用右孩子顶替该节点
5)如果该节点有左孩子、有右孩子,用该节点后继节点顶替该节点

搜索二叉树特别不讲究

1)基础的搜索二叉树,添加、删除时候不照顾平衡性
2)数据状况很差时,性能就很差

给搜索二叉树引入两个动作:左旋、右旋

AVL树、SB树、红黑树的共性

1)都是搜索二叉树
2)插入、删除、查询(一切查询)搜索二叉树怎么做,这些结构都这么做
3)使用调整的基本动作都只有左旋、右旋
4)插入、删除时,从最底层被影响到的节点开始,对往上路径的节点做平衡性检查
5)因为只对一条向上路径的每个节点做O(1)的检查和调整,所以可以做到O(logN)

AVL树、SB树、红黑树的不同

1)平衡性的约束不同
AVL树最严格、SB树稍宽松、红黑树最宽松
2)插入、删除和搜索二叉树一样,但是额外,做各自的平衡性调整。各自的平衡性调整所使用的动作都是左旋或者右旋

AVL树

1)最严格的平衡性,任何节点左树高度和右树高度差不超过1
2)往上沿途检查每个节点时,都去检查四种违规情况:LL、RR、LR、RL
3)不同情况虽然看起来复杂,但是核心点是:
LL(做一次右旋)、RR(做一次左旋)
LR和RL(利用旋转让底层那个上到顶部)
当即为LL,也为LR时,用LL的方法
当既为RR,也为RL时,用RR的方法

AVL数

public static class AVLNode, V> {
		public K k;
		public V v;
		public AVLNode l;
		public AVLNode r;
		public int h;

		public AVLNode(K key, V value) {
			k = key;
			v = value;
			h = 1;
		}
	}

	public static class AVLTreeMap, V> {
		private AVLNode root;
		private int size;

		public AVLTreeMap() {
			root = null;
			size = 0;
		}

		private AVLNode rightRotate(AVLNode cur) {
			AVLNode left = cur.l;
			cur.l = left.r;
			left.r = cur;
			cur.h = Math.max((cur.l != null ? cur.l.h : 0), (cur.r != null ? cur.r.h : 0)) + 1;
			left.h = Math.max((left.l != null ? left.l.h : 0), (left.r != null ? left.r.h : 0)) + 1;
			return left;
		}

		private AVLNode leftRotate(AVLNode cur) {
			AVLNode right = cur.r;
			cur.r = right.l;
			right.l = cur;
			cur.h = Math.max((cur.l != null ? cur.l.h : 0), (cur.r != null ? cur.r.h : 0)) + 1;
			right.h = Math.max((right.l != null ? right.l.h : 0), (right.r != null ? right.r.h : 0)) + 1;
			return right;
		}

		private AVLNode maintain(AVLNode cur) {
			if (cur == null) {
				return null;
			}
			int leftHeight = cur.l != null ? cur.l.h : 0;
			int rightHeight = cur.r != null ? cur.r.h : 0;
			if (Math.abs(leftHeight - rightHeight) > 1) {
				if (leftHeight > rightHeight) {
					int leftLeftHeight = cur.l != null && cur.l.l != null ? cur.l.l.h : 0;
					int leftRightHeight = cur.l != null && cur.l.r != null ? cur.l.r.h : 0;
					if (leftLeftHeight >= leftRightHeight) {
						cur = rightRotate(cur);
					} else {
						cur.l = leftRotate(cur.l);
						cur = rightRotate(cur);
					}
				} else {
					int rightLeftHeight = cur.r != null && cur.r.l != null ? cur.r.l.h : 0;
					int rightRightHeight = cur.r != null && cur.r.r != null ? cur.r.r.h : 0;
					if (rightRightHeight >= rightLeftHeight) {
						cur = leftRotate(cur);
					} else {
						cur.r = rightRotate(cur.r);
						cur = leftRotate(cur);
					}
				}
			}
			return cur;
		}

		private AVLNode findLastIndex(K key) {
			AVLNode pre = root;
			AVLNode cur = root;
			while (cur != null) {
				pre = cur;
				if (key.compareTo(cur.k) == 0) {
					break;
				} else if (key.compareTo(cur.k) < 0) {
					cur = cur.l;
				} else {
					cur = cur.r;
				}
			}
			return pre;
		}

		private AVLNode findLastNoSmallIndex(K key) {
			AVLNode ans = null;
			AVLNode cur = root;
			while (cur != null) {
				if (key.compareTo(cur.k) == 0) {
					ans = cur;
					break;
				} else if (key.compareTo(cur.k) < 0) {
					ans = cur;
					cur = cur.l;
				} else {
					cur = cur.r;
				}
			}
			return ans;
		}

		private AVLNode findLastNoBigIndex(K key) {
			AVLNode ans = null;
			AVLNode cur = root;
			while (cur != null) {
				if (key.compareTo(cur.k) == 0) {
					ans = cur;
					break;
				} else if (key.compareTo(cur.k) < 0) {
					cur = cur.l;
				} else {
					ans = cur;
					cur = cur.r;
				}
			}
			return ans;
		}

		private AVLNode add(AVLNode cur, K key, V value) {
			if (cur == null) {
				return new AVLNode(key, value);
			} else {
				if (key.compareTo(cur.k) < 0) {
					cur.l = add(cur.l, key, value);
				} else {
					cur.r = add(cur.r, key, value);
				}
				cur.h = Math.max(cur.l != null ? cur.l.h : 0, cur.r != null ? cur.r.h : 0) + 1;
				return maintain(cur);
			}
		}

		// 在cur这棵树上,删掉key所代表的节点
		// 返回cur这棵树的新头部
		private AVLNode delete(AVLNode cur, K key) {
			if (key.compareTo(cur.k) > 0) {
				cur.r = delete(cur.r, key);
			} else if (key.compareTo(cur.k) < 0) {
				cur.l = delete(cur.l, key);
			} else {
				if (cur.l == null && cur.r == null) {
					cur = null;
				} else if (cur.l == null && cur.r != null) {
					cur = cur.r;
				} else if (cur.l != null && cur.r == null) {
					cur = cur.l;
				} else {
					AVLNode des = cur.r;
					while (des.l != null) {
						des = des.l;
					}
					cur.r = delete(cur.r, des.k);
					des.l = cur.l;
					des.r = cur.r;
					cur = des;
				}
			}
			if (cur != null) {
				cur.h = Math.max(cur.l != null ? cur.l.h : 0, cur.r != null ? cur.r.h : 0) + 1;
			}
			return maintain(cur);
		}

		public int size() {
			return size;
		}

		public boolean containsKey(K key) {
			if (key == null) {
				return false;
			}
			AVLNode lastNode = findLastIndex(key);
			return lastNode != null && key.compareTo(lastNode.k) == 0 ? true : false;
		}

		public void put(K key, V value) {
			if (key == null) {
				return;
			}
			AVLNode lastNode = findLastIndex(key);
			if (lastNode != null && key.compareTo(lastNode.k) == 0) {
				lastNode.v = value;
			} else {
				size++;
				root = add(root, key, value);
			}
		}

		public void remove(K key) {
			if (key == null) {
				return;
			}
			if (containsKey(key)) {
				size--;
				root = delete(root, key);
			}
		}

		public V get(K key) {
			if (key == null) {
				return null;
			}
			AVLNode lastNode = findLastIndex(key);
			if (lastNode != null && key.compareTo(lastNode.k) == 0) {
				return lastNode.v;
			}
			return null;
		}

		public K firstKey() {
			if (root == null) {
				return null;
			}
			AVLNode cur = root;
			while (cur.l != null) {
				cur = cur.l;
			}
			return cur.k;
		}

		public K lastKey() {
			if (root == null) {
				return null;
			}
			AVLNode cur = root;
			while (cur.r != null) {
				cur = cur.r;
			}
			return cur.k;
		}

		public K floorKey(K key) {
			if (key == null) {
				return null;
			}
			AVLNode lastNoBigNode = findLastNoBigIndex(key);
			return lastNoBigNode == null ? null : lastNoBigNode.k;
		}

		public K ceilingKey(K key) {
			if (key == null) {
				return null;
			}
			AVLNode lastNoSmallNode = findLastNoSmallIndex(key);
			return lastNoSmallNode == null ? null : lastNoSmallNode.k;
		}

	}

你可能感兴趣的:(算法)