《算法导论》笔记(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,一个状态指示怎么走,前进或者后退状态,不同条件下翻转。
习题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,然后左旋。右旋时同理。
思考题13-4 treap树。插入后,检查x与x.p的priority,若需要交换,x在左则右旋,x在右则左旋。
习题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;} } }
相关文章推荐
- 《算法导论》笔记(10)贪心算法 部分习题
- 《算法导论》笔记(18) 最大流 含部分习题
- 《算法导论》笔记(9) 动态规划 部分习题
- 《算法导论》笔记(1)排序 含部分习题
- 《算法导论》笔记(11) 摊还分析 部分习题
- 《算法导论》笔记(16) 单源最短路径 部分习题
- 《算法导论》笔记(15) 最小生成树 部分习题
- 《算法导论》笔记(5)链表到红黑树
- 《算法导论》笔记(14) 基本的图算法 部分习题
- 《算法导论》笔记(17) 所有结点对最短路径 部分习题
- 《算法导论》笔记(4)堆排序与快速排序 含部分习题
- 算法导论-3.递归部分习题选
- 【原创】《算法导论》链表一章带星习题试解——附C语言实现
- 《算法导论》读书笔记(2)复杂度、分治策略 部分习题
- 《算法导论》笔记 第10章 10.2 链表
- 《算法导论》笔记 第10章 10.2 链表
- 算法导论学习笔记-第十三章-红黑树
- 算法导论学习笔记(3)-习题2.3-7-排序+二分
- 《算法导论》笔记 第13章 13.1 红黑树的性质
- 算法导论笔记之----双向链表