二叉树操作

来源:互联网 发布:mac上的杀毒软件 编辑:程序博客网 时间:2024/06/05 00:15
1、重构二叉树:
(1)已知前序、中序,可以唯一确定一个二叉树;
(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;i 0)                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,则该二叉排序树就是不平衡的。

转发平衡二叉树:http://www.cnblogs.com/suimeng/p/4560056.html

4、红黑树
定义:满足如下性质的二叉排序树:
(1)每个结点要么是红的,要么是黑的。
(2)根结点是黑的。
(3)每个叶结点,即空结点(NIL)是黑的。
(4)如果一个结点是红的,那么它的俩个儿子都是黑的。
(5)对每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点。
原创粉丝点击