《算法》第四版的源代码: http://algs4.cs.princeton.edu/code/ ,看了看还是很有收获!
相同点:
1、链表 :Node包括(value (不一定存什么类型!!!), next , N(可以添加一个参数)) 二叉查找树 Node(value(一个键值对,key负责节点的操作,value负责节点存储的信息) , right , left ,N(以该根节点的子节点的节点的个数))
2、链表(必要元素 head):入口是head,每当我们要操作链表的时候,都要保证新链表的head的正确性;
二叉树(必要元素 root):入口是root,二叉树也一样,时刻也要保证是否还是原来的root;而且什么参数都要和root进行比较;
3、为什么使用二叉查找树: 集二分查找和链表的优点于一身!
4、二分查找:
//迭代思想的 二分查找 ,先排序,后查找
public int rank(Key key){
int lo = 0;
int hi = N-1;
while(lo<hi){
int mid = (lo + hi) / 2;
//这里的compareTo对任意扩展于comparable的类都能做比较!!!
int cmp = key.compareTo(key[mid]);
if(cmp == 0) return mid;
if(cmp < 0) hi = mid - 1;
if(cmp > 0) lo = mid + 1;
}
return lo;
}
5、对链表的操作:
1、设置快慢指针(一个先走,一个等等);
2、设置两个同步指针(只是两个指针的步子不同,一个一次一步,一个一次两步);
3、声明一个新的节点。将即将要被操作的节点存到里面,操作完以后再为下一次做准备;
//特别是要对某个节点做操作时,因为两个节点之间是有联系的!后面的节点还要用到节点变化之前的关系。
对树的操作:递归,中序遍历;
//我们调用detele时,都是调用下面这个方法,但是这个方法并没有返回值,因此不能利用递归去操作节点;所以我们可以重载一个私有方法,来封装这个操作的逻辑,调用的时候,有专门的方法去负责调用即可;
//有返回值,这样递归更简单!!
public void delete(Key key){
root = delete(root , key);
}
//始终都是操作root
//要理解递归的含义!
private Node delete(Node x , Key key){
if(x == null) return null;
//先找key
int cmp = key.compareTo(x.key);
if(cmp > 0) x.right = delete(x.right , key); //这个地方要注意,递归是一个栈,括号里的x和外面的x是不同的,相当于外面的x是栈上一层的x!!
if(cmp < 0) x.left = delete(x.left , key);
else if {
//找到后,判断其左右的两个子节点
Node t = x; //这里new一个新的节点,存储要被删除的x的信息!!!!来代表原来的x
if(x.right == null) return x.left; //这一步展示出来断开;这一步,说明将x的左节点连到x的上层,以代替x的位置;
if(x.left == null) return x.right;
//如果两个子节点都不为空!
x = min(t.right);
x.right = t.right ;
x.left = t.left;
}
x.N = size(x.left) + size(x.right) +1;
return x;
}
题外:
1、对某个类(extends comparable 这个接口,利用(重写)其中的compareTo方法,找到这个类的两个对象的比较原则,返回0,-1,1)
2、然后对这些个对象(一般存在数组或集合中),利用sort()方法,将这些个对象进行排序;
3、排好序,就可以导入相应的查找效率较高的数据结构;
4、在这些个数据结构中,利用其提供的方法,进行操作;
疑问:
1、普通二叉树,怎么转换到二叉查找树,,,(或许,怎么把排好序的数组 -> 二叉查找树? 中序遍历)