您的位置:首页 > 其它

《算法导论》笔记(6)链表到红黑树 部分习题

2015-02-05 15:28 337 查看
习题10.2-8, 记第i个元素的np为np1,np2… 则np0xor np1 xor np2 xor np3 ….npi得到npixor np0,np0是表头的地址。若定义np0为0x00000000,(np1xor np2 xor np3…. xor npi)即为第i+1个元素的相对地址。若要逆转链表,则查找时从最末位向前连续xor即可。

习题10.4-5 二叉树那章有道题相同,不用栈不用递归遍历。访问方法是几条移动规则:1,到底则向上移,2,向右上则输出1个元素z并移动到minimum(z.right),3,向左上不输出,4,一个状态指示怎么走,前进或者后退状态,不同条件下翻转。

minimum(x){
if x.right!=null x=x.right;
if x.left!=null x=x.left;
while(x.left) x=x.left; return x;
}
walk(x){
x=minimum(x);
direction=forward;
while(x!=root){
if(direction==forward) visit(x);
if(x.right==null){direction=backward; continue;}
if(x==x.p.left && direction==forward) {if(x.right!=null) x=minimum(x); else x=x.p; continue;}
if(x==x.p.left && direction==backward) {x=x.p; direction=forward; continue;}
if(x==x.p.right && direction=backward) {x=x.p; continue;}
if(x==x.p.right && direction==forward) {x=minimum(x); continue;}
}
}


习题10.4-6 左孩子右兄弟表示法需要3个指针,前驱,后继,孩子,那么只用2个指针的方法就是将前驱和后继异或,布尔变量表示第一个兄弟,它的指针是父指针与弟指针的异或。遍历方法同10.2-8

思考题12-1 相同关键字的二叉搜索树。红黑树中的应用就是mulitset和multimap。如果是随机在x.left或x.right插入相同元素,那么随着旋转操作,可能出现相同元素并不连接在一起的问题。搜索x得到第一个x,为了搜索后续的x,需要递归搜索x的左子树和右子树。那么最差性能是O(mi*lg(n)),m是重复元素的个数。如果是在重复元素处加一个表记录所有相同重复元素的位置,那么每次需更新全部的表,开销更大。

思考题12-2 基数树。想起了哈夫曼编码。

习题13.3-6 没有父指针的红黑树插入过程。猜测方法是用search_p(k)函数找到父结点,并判断是父结点的左孩子还是右孩子。

习题13.4-7 插入时,考察插入元素及其父叔的情况,删除是逆过程,而且只要不再插入新的元素,删除后的树与原来保持一致

思考题13-3 AVL树。左右子树高度差大于1,则右旋或左旋。左子树hl,其左右枝为hll,hlr,右子树hr,其左右枝为hrl,hrr。左旋时,hll与hlr高度+1,hrl高度-1,hrr高度-2,所以对于左低右高的情况,若hrl高于hrr则先右旋右子树保证hrl不高于hrr,然后左旋。右旋时同理。

balance(x){
if(x.l.h<x.r.h){
if(x.r.l.h>x.r.r.h) right_rotate(x.r);
left_rotate(x);
}
if(x.l.h>x.r.h){
if(x.l.l.h<x.l.r.h) left_rotate(x.l);
right_rotate(x);
}
}
insert(x,k){
x=find_and_add(x,k);
while(x!=null) {x=x.p; balance(x);};
}
find_and_add(x,k){
if(x.r==null && k>x.value) {x.r.add(k); x=x.r;}
elseif(x.l==null && k<x.value) {x.l.add(k); x=x.l;}
return x;
if(k>x.value) find_and_add(x.r, k);
if(k<x.value) find_and_add(x.l, k);
}


思考题13-4 treap树。插入后,检查x与x.p的priority,若需要交换,x在左则右旋,x在右则左旋。

balance(x){
if(x=x.p.right && x.priority>x.p.priority) left_rotate(x.p);
if(x=x.p.left && x.priority>x.p.priority) right_rotate(x.p);
}
insert(x,k){
x=find_and_add(x,k);
while(x!=root) balance(x);
}
但是如果一种方法,不把新元素加入到最底层,而是直接插入到两个元素之间,x.p.priority<z.priority<x.priority,那么将z插入到x.p与x之间,并调整z、x、x.p的左右关系。插入时不需要旋转。

insert(x,k){
while(k.priority>x.priority){
if(k.value>x.value) {if(x.right) {x=x.right; continue;} else{x.add_right(k); return;}}
elseif(k.value<x.value) {if(x.left) {x=x.left; continue;} else{x.add_left(k); return;}}
}
if(x==x.p.left) {
if(k>x.value) { x.p.add_left(k); k.add_left(x); return;}
elseif(k<x.value) { x.p.add_right(k); k.add_right(x); return;}
}
if(x==x.p.right) {
if(k>x.p.value){ x.p.add_right(k); k.add_left(x); return;}
elseif(k<x.p.value){ x.p.add_right(k); k.add_right(x); return;}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: