二叉树操作

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 child
	if(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 -> next
void 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)对每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值