二叉树操作
来源:互联网 发布:mac上的杀毒软件 编辑:程序博客网 时间:2024/06/05 00:15
1、重构二叉树:
(1)已知前序、中序,可以唯一确定一个二叉树;
(2)已知后序、中序,可以唯一确定一个二叉树;
(3)但是已知前序、后序却不能确定一棵二叉树;
(2)已知后序、中序,可以唯一确定一个二叉树;
(3)但是已知前序、后序却不能确定一棵二叉树;
2、二叉树操作相关:
/*二叉树数据结构*/typedef struct bitree{ int data; struct bitree *l; struct bitree *r;}B_TREE_T;/*创建操作*/B_TREE_T* create(int *aa, int len){ int i = 0; B_TREE_T * t = NULL; for(i = 0;i < len;i++) { t = insert(t, aa[i]); } return t;}/*插入操作*/B_TREE_T * insert(B_TREE_T *t, int key){ if(NULL == t) { t = (B_TREE_T* )malloc(sizeof(B_TREE_T)); t->l = NULL; t->r = NULL; t->data = key; return t; } else if(key < t->data) { t->l = insert(t->l, key); } else { t->r = insert(t->r, key); } return t;}/*前序遍历*/void first_v(B_TREE_T *t){ if(NULL == t) return; printf(" %d", t->data); if(t->l) first_v(t->l); if(t->r) first_v(t->r); return;}/*中序遍历*/void middle_v(B_TREE_T *t){ if(NULL == t) return; if(t->l) middle_v(t->l); printf(" %d", t->data); if(t->r) middle_v(t->r);}/*后序遍历*/void after_v(B_TREE_T *t){ if(NULL == t) return; if(t->l) after_v(t->l); if(t->r) after_v(t->r); printf(" %d", t->data);}/*层次遍历*/int level_v(B_TREE_T *t, int level){ if(NULL == t) return 0; if(0 == level) { printf(" %d", t->data); return 1; } return level_v(t->l, level-1) + level_v(t->r, level-1);}/*查询操作*/int search(B_TREE_T *t, int key){ if(NULL == t) return 0; if(key == t->data) { printf("Found it\n"); return 1; } if(key < t->data) { return search(t->l, key); } else { return search(t->r, key); } return 0;}/*树深度*/int depth(B_TREE_T *t){ return t? max(depth(t->l), depth(t->r))+1 : 0;}/*翻转操作*/B_TREE_T* reverse(B_TREE_T *t){ B_TREE_T *tmp; if(NULL == t) return NULL; reverse(t->l); reverse(t->r); tmp = t->l; t->l = t->r; t->r = tmp;}/*删除操作*//*删除节点有如下几种情况:1、若*p结点为叶子结点,即PL(左子树)和PR(右子树)均为空树。 由于删去叶子结点不破坏整棵树的结构,则可以直接删除此子结点。2、若*p结点只有左子树PL或右子树PR,此时只要令PL或PR直接成为其双亲结点*f的左子树(当*p是左子树) 或右子树(当*p是右子树)即可,作此修改也不破坏二叉排序树的特性。2、若*p结点的左子树和右子树均不空。在删去*p之后,为保持其它元素之间的相对位置不变, 可按中序遍历保持有序进行调整,可以有两种做法:(1)令*p的左子树为*f的左/右(依*p是*f的左子树还是右子树而定)子树, *s为*p左子树的最右下的结点,而*p的右子树为*s的右子树;(2)令*p的直接前驱(或直接后继)替代*p,然后再从二叉排序树中删去它的直接前驱(或直接后继) 即让*f的左子树(如果有的话)成为*p左子树的最左下结点(如果有的话),再让*f成为*p的左右结点的父结点。*/int delete(B_TREE_T *t, int key){B_TREE_T *q,*p = t;int flag = 0;while(p && !flag){if(key == p->data){flag = 1;}else if(key < p->data){q = p;p = p->l;}else{q = p;p = p->r;}}if(0 == flag)return -1;//no childif(NULL == p->l && NULL == p->r){if(p == t){t = NULL;}else if(q->l == p){q->l = NULL;}else{q->r = NULL;}free(p);}else if(NULL == p->l || NULL == p->r){if(p == t){if(NULL == p->l){t = p->r;}else{t = p->l;}}else{if(q->l == p && p->l){q->l = p->l;}else if(q->l == p && p->r){q->l = p->r;}else if(q->r == p && p->l){q->r = p->l;}else{q->r = p->r;}}free(p);}else{B_TREE_T *k = p;B_TREE_T *s = p->l;while(s->r){k = s;s = s->r;}p->data = s->data;if(k == p){p->l = s->l;}else{k->r = s->l;}free(s);}return flag;}/*根据前序、中序重建二叉树*/B_TREE_T *constrcut1(int *pre, int *mid, int len){ int i = 0; int data = pre[0]; B_TREE_T *tmp = NULL; if(NULL == pre || NULL == mid || len <=0) return NULL; tmp = (B_TREE_T *)malloc(sizeof(B_TREE_T)); if(NULL == tmp) { printf("Failed to malloc tree node!\n"); return NULL; } tmp->data = data; tmp->l = tmp->r = NULL; for(i = 0;i0) tmp->l = constrcut1(&pre[1],&mid[0],lenL); if(lenR > 0) tmp->r = constrcut1(&pre[lenL+1], &mid[lenL+1], lenR); return tmp;}/*非递归前序遍历*/void first_order_nonrecursion(B_TREE_T *t) { B_TREE_T *p = root; stack s; if (root == NULL) return; while (!s.empty() || p) { //边遍历边打印,并存入栈中,以后需要借助这些根节点(不要怀疑这种说法哦)进入右子树 while (p) { cout << setw(4) << p->data; s.push(p); p = p->lchild; } //当p为空时,说明根和左子树都遍历完了,该进入右子树了 if (!s.empty()) { p = s.top(); s.pop(); p = p->rchild; } } cout << endl; }/*非递归中序遍历*/void mid_order_nonrecursive(B_TREE_T *t){B_TREE_T *p = root; stack s; if(NULL == t) return; while (!s.empty() || p) { //一直遍历到左子树最下边,边遍历边保存根节点到栈中 while (p) { s.push(p); p = p->lchild; } //当p为空时,说明已经到达左子树最下边,这时需要出栈了 if (!s.empty()) { p = s.top(); s.pop(); cout << setw(4) << p->data; //进入右子树,开始新的一轮左子树遍历(这是递归的自我实现) p = p->rchild; } } }/*非递归后序遍历*/void last_order_nonrecursive(B_TREE_T T) // 后序遍历的非递归 双栈法 { stack s1 , s2; B_TREE_T curr ; // 指向当前要检查的节点 s1.push(T); while(!s1.empty()) // 栈空时结束 { curr = s1.top(); s1.pop(); s2.push(curr); if(curr->lchild) s1.push(curr->lchild); if(curr->rchild) s1.push(curr->rchild); } while(!s2.empty()) { printf("%c ", s2.top()->data); s2.pop(); } }/*二叉树转换为排序链表*///tree -> list//left -> prev//right -> nextvoid convertNode(B_TREE_T *t, B_TREE_T **list){ B_TREE_T *cur = t; if(NULL == t) return; if(NULL != cur->l) convertNode(cur->l, list); cur->l = *list; if(NULL != *list) (*list)->r = cur; *list = cur; if(NULL != cur->r) convertNode(cur->r, list);}B_TREE_T *convert(B_TREE_T *t){ B_TREE_T *headlist; B_TREE_T *list = NULL; convertNode(t, &list); headlist = list; while(headlist != NULL && headlist->l != NULL) headlist = headlist->l; return headlist;}
3、平衡二叉树
定义:平衡二叉树或为空树,或为如下性质的二叉排序树:
(1)左右子树深度之差的绝对值不超过1;
(2)左右子树仍然为平衡二叉树。
平衡因子BF=左子树深度-右子树深度.
平衡二叉树每个结点的平衡因子只能是1,0,-1。若其绝对值超过1,则该二叉排序树就是不平衡的。
(1)左右子树深度之差的绝对值不超过1;
(2)左右子树仍然为平衡二叉树。
平衡因子BF=左子树深度-右子树深度.
平衡二叉树每个结点的平衡因子只能是1,0,-1。若其绝对值超过1,则该二叉排序树就是不平衡的。
转发平衡二叉树:http://www.cnblogs.com/suimeng/p/4560056.html
4、红黑树
定义:满足如下性质的二叉排序树:
(1)每个结点要么是红的,要么是黑的。
(2)根结点是黑的。
(3)每个叶结点,即空结点(NIL)是黑的。
(4)如果一个结点是红的,那么它的俩个儿子都是黑的。
(5)对每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点。
(1)每个结点要么是红的,要么是黑的。
(2)根结点是黑的。
(3)每个叶结点,即空结点(NIL)是黑的。
(4)如果一个结点是红的,那么它的俩个儿子都是黑的。
(5)对每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点。
阅读全文
1 0
- 二叉树的操作
- 二叉树的操作
- 二叉树的操作
- 二叉树常用操作
- 二叉树的操作
- 二叉树 常见操作
- 二叉树基本操作
- 二叉树相关操作
- 二叉树 基本操作
- 二叉树的操作
- 二叉树基本操作
- 二叉树操作
- 二叉树 一些操作
- 二叉树操作
- 数据结构-二叉树操作
- 二叉树的操作
- 二叉树操作
- 二叉树的操作
- oracle update select ,从A中select后写入B
- QTextEdit 插入Html 表格(table)
- 泛型<?super T> 和<? extends T>区别
- iOS银联网页支付出现的界面没有适配手机端的解决办法!
- 只有年月的输入框
- 二叉树操作
- Spring IOC三种注入方式(接口注入、setter注入、构造器注入)
- Android EditText 文本内容超过文本框失去焦点后,超出文本框内容显示...
- android驱动USB摄像头了
- AI/机器学习/深度学习三者的区别是什么?
- Android系统启动过程简介
- Dlubal RX-TIMBER 2.09.01 Win64 1CD
- 面试题目:125!除以10^31的余数为多少?
- ArrayList和LinkedList的区别