`
haoningabc
  • 浏览: 1482239 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

二叉树

    博客分类:
  • c
阅读更多
转http://www.cnblogs.com/fornever/archive/2011/11/15/2249492.html
一句话,出来混,早晚是要还的,天天弄java,mlgbd基础全忘光了
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef int Elemtype;

typedef struct Balanced_Binary_Tree
{
    Elemtype e;
    int bf;
    struct Balanced_Binary_Tree *child[2];
}*AVL;

///------------简单的位操作-------------------
void setbit(char *i,char val,char pos)
{
    if(pos==1)
        (*i)=(*i)|1;
    else
    {
        if(val==1)    (*i)=(*i)|2;
        else    (*i)=(*i)&1;
    }
}
char getbit(char i,char pos)
{
    ///调试时,发现这里能返回2///
//    return (i&pos); 出错的地方
    return (i&pos)&&1;
    /////////////////////////////
}
///--------------------------------------------

///-----------生成一个结点---------------------
AVL createnode(Elemtype e)
{
    AVL node=NULL;

    node=(AVL)malloc(sizeof(struct Balanced_Binary_Tree));
    node->e=e;    node->bf=0;
    node->child[0]=node->child[1]=NULL;
    
    return node;
}
///---------------------------------------------

///★★★★★★★★AVL的核心操作★★★★★★★★★★★★
///★★★★★★★★★保持平衡★★★★★★★★★★★★★★

//改变因子函数
void setfactor(AVL f,int button)
{
    char fir=button/10,sec=button%10;
    AVL s=f->child[fir],ss=s->child[sec];
    char choice=ss->bf;
    int a=1,b=0;

    //////////调试时发现,删除时的特殊情况/////////////
/////插入时,不会有这种情况,若button=0,则s->bf=1//
/////若button=11,则s->bf=-1;然而删除时,却会出现/
/////button=0或者button=11时 s->bf=0!!!!!!!////////
/////那么这种特殊情况,平衡后所得的因子就跟一般的//
/////不一样了!!!如下///////////////////////////////
    if(button==0 && s->bf==0)    f->bf=1,s->bf=-1;
    else if(button==11 && s->bf==0)    f->bf=-1,s->bf=1;
    ///////////////////////////////////////////////////
    else if(button==0 || button==11)
    {
        f->bf=0;
        s->bf=0;
    }
    else
    {
        /////写博客时,发现这里有问题///////////////////
    //    if(button==1)    choice=-choice;
        /////但是为什么我测试的时候怎么都对?!///////////
/////经再次测试,上边确实错了!!!////////////////
/////改为下边应该就对了吧///////////////////////
        if(button==1)    {a^=b,b^=a,a^=b;}
        ////////////////////////////////////////////////

        if(choice==-1)    f->bf=a,s->bf=b;
        else if(choice==0)    f->bf=s->bf=0;
        else    f->bf=-b,s->bf=-a;
        
        ss->bf=0;
    }
}
//两节点变换函数
void conversion(AVL *T,char direction)
{
    AVL f=*T,s=f->child[direction];

    f->child[direction]=s->child[!direction];
    s->child[!direction]=f;
    *T=s;
}
//保持平衡函数
void keepbalance(AVL *T,char fir,char sec)
{
    AVL *s=&((*T)->child[fir]);
    int button=fir*10+sec;

    if(button==0 || button==11)
    {
        setfactor((*T),button);
        conversion(T,fir);
    }
    else
    {
        setfactor((*T),button);
        conversion(s,sec);
        conversion(T,fir);
    }
}
///★★★★★★★★★★★★★★★★★★★★★★★★★★

///------------插入时的选向操作-------------------
void selectforInsert(AVL *T,char *info,int direction)
{
    AVL cur=*T;
    char firdirection,secdirection;

    if(direction==0)    (cur->bf)++;
    else    (cur->bf)--;

    if(cur->bf==0)    setbit(info,1,1);
    else if(cur->bf==-1 || cur->bf==1)    setbit(info,direction,2);
    else
    {        
        firdirection=direction;
        secdirection=getbit(*info,2);
        keepbalance(T,firdirection,secdirection);
        setbit(info,1,1);
    }
}
//----------------------------------------------

//*************插入操作************************//
char InsertAVL(AVL *T,Elemtype e)
{                                //可用于查询
    char info;
    
    if(!(*T))
    {
        (*T)=createnode(e);
        return 0;
    }
    else if((*T)->e==e)        return -1;
    else if((*T)->e>e)//左
    {
        info=InsertAVL(&((*T)->child[0]),e);

        if(getbit(info,1))    return info;
        
        selectforInsert(T,&info,0);
    }
    else              //右
    {
        info=InsertAVL(&((*T)->child[1]),e);

        if(getbit(info,1))    return info;

        selectforInsert(T,&info,1);
    }
    return info;
}
//*********************************************//

//-------------删除时的选向操作--------------------
void selectforDelete(AVL *T,char *info,char direction)
{
    AVL cur=(*T);
    char firdirection,secdirection;

    if(direction==0)    (cur->bf)--;
    else    (cur->bf)++;
    
    if(cur->bf==0)    *info=0;
    else if(cur->bf==-1 || cur->bf==1)    *info=1;
    else
    {
        firdirection=!direction;
        ///调试时,发现这里少写了一个等号////////////////////
//        if(cur->child[firdirection]->bf=1)    secdirection=0;草,真帅气!原来1==a这样写确实有必要!
        if(1==cur->child[firdirection]->bf)    secdirection=0;
        /////////////////////////////////////////////////////
        else    secdirection=1;
        keepbalance(T,firdirection,secdirection);

        /////////////////////////////////////////////////////////////////////////////////////////
///调试时,发现经过子树平衡操作后,*info不一定都是0,就是那个特殊情况,在setfactor中/////
///的那种特殊情况时,这里*info应改为1! 所以代码改如下://////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
    //    *info=1; 写代码时:这跟插入可不一样啊...该子树平衡了,它父节点的因子比变!
//    *info=0;//因此,这还没完还要是0!! ............啊……这里不一定是0! 
////还是那个特殊情况搞的鬼!//
        if(cur->bf==0)    *info=0;
        else    *info=1;
        /////////////////////////////////////////////////////////////////////////////////////////
    }
}
//------------------------------------------------

//-------------变向递归--辅助删点-----------------
char find(AVL *gogal,AVL *p)
{
    char info;
    AVL tp=NULL;
    
    if(NULL!=(*p)->child[0])
    {
        info=find(gogal,&((*p)->child[0]));
        if(info!=0)    return info;
        selectforDelete(p,&info,0);
    }
    else
    {
        (*gogal)->e=(*p)->e;
        tp=(*p)->child[1];
        free((*p));
        *p=tp;
        info=0;
    }
    return info;
}
//------------------------------------------------

//**************删除操作*************************//
char DeleteAVL(AVL *T,Elemtype e)
{
    char info;
    AVL tp=NULL;

    if(!(*T))    return -1;//原if(!T)    return -1;于2011年11月29日8:59:15修改
    else if((*T)->e==e)
    {
        if(NULL!=(*T)->child[1])
        {
            info=find(T,&((*T)->child[1]));
            if(info!=0)    return info;
            selectforDelete(T,&info,1);
        }
        else
        {
            //////////////调试时,发现这样写不对!!!///////////////////////////////////////
        //    (*T)=(p=(*T)->child[0])-(free((*T)),0);//Just save a variable! 这里出问题
//    (*T)=p-(free((*T)),0); 可以
//    (*T)=(p=((*T)->child[0]))+(free((*T)),0); 不可以
            tp=((*T)->child[0]);
            free((*T));
            *T=tp;
            //调试时,发现这里漏了给info赋值
            info=0;
            ///////////////////////////////////////////////////////////////////////////////
        }
    }
    else if((*T)->e>e)
    {
        info=DeleteAVL(&(*T)->child[0],e);
        if(info!=0)    return info;
        selectforDelete(T,&info,0);
    }
    else
    {
        info=DeleteAVL(&(*T)->child[1],e);
        if(info!=0)    return info;
        selectforDelete(T,&info,1);
    }
    return info;
}
//************************************************//


//*****************JUST FOR TEST************************//
#define MOVE(x)    (x=(x+1)%1000)
AVL queue[1000];

void print(AVL p,int i)
{
    int front,rear,temp,count;

    front=rear=-1; count=temp=0;
    queue[MOVE(rear)]=p; count++;
    
    printf("%d\n",i);
    while(front!=rear)
    {
        p=queue[MOVE(front)];    count--;
        
        
        if(p->child[0])    queue[MOVE(rear)]=p->child[0],temp++;
        if(p->child[1])    queue[MOVE(rear)]=p->child[1],temp++;
        
        printf("%d->%d ",p->e,p->bf);
        if(count==0)
        {
            printf("\n");
            count=temp;
            temp=0;
        }    
    }
    printf("\n");
}
//**************************************************//


int main()
{
    AVL T=NULL;
    int i,nodenum=0;

    freopen("input.txt","w",stdout);
    nodenum=100;
    for(i=0;i<nodenum;i++)
    {
        InsertAVL(&T,i);
    }
    
    print(T,-1);

    for(i=0;i<nodenum-1;i++)
    {
        DeleteAVL(&T,i);
        print(T,i);
    }
    
    return 0;
}
分享到:
评论

相关推荐

    二叉树深度_二叉树查询_二叉树深度_

    二叉树是一种在计算机科学中广泛应用的数据结构,它由节点(也称为结点)组成,每个节点最多有两个子节点,通常称为左子节点和右子节点。二叉树的深度是指从根节点到最远叶节点的最长路径上边的数目,即树的最大层数...

    二叉树演示 实现二叉树图形显示

    二叉树是一种特殊的树结构,每个节点最多只有两个子节点,通常分为左子节点和右子节点。在计算机科学中,二叉树被广泛应用于数据的组织和操作,如搜索、排序、文件系统等。本例子关注的是如何实现二叉树的图形显示,...

    根据后序二叉树序列构造二叉树_扩展二叉树

    在计算机科学领域,二叉树是一种基础的数据结构,它由结点构成,每个结点最多有两个子节点,分别称为左子节点和右子节点。在众多的二叉树操作中,根据后序遍历序列(也称为后序序列)来构造二叉树是一项常见的任务。...

    二叉树建立 二叉树基本算法的实现

    (2)先序、中序、后序遍历二叉树:递归算法。 (3)中序遍历二叉树:非递归算法(最好也能实现先序,后序非递归算法)。 (4)求二叉树的高度 。 (5)求二叉树的叶子个数。 (6)对于树中每一个元素值为x的结点...

    第六章 树和二叉树作业及答案(100分).docx

    - **答案解析**:如果一棵二叉树的中序遍历序列和后序遍历序列正好相反,那么该二叉树一定是任一结点都没有左孩子的二叉树。 #### 5. 二叉树的结点数范围 - **答案解析**:深度为k的二叉树最多有\(2^k - 1\)个结点...

    将满二叉树转化为求和二叉树_二叉树_

    在IT领域,特别是数据结构和算法的学习中,二叉树是一种重要的抽象数据类型。满二叉树是一种特殊的二叉树,其中每一层都是完全填充的,除了可能的最后一层,且最后一层的所有节点都尽可能地向左靠拢。而将满二叉树...

    二叉树的各种操作各种遍历,复制,求高度,判断是否为一棵完全二叉树以及计算用二叉树存储的表达式

    根据给定的信息,本文将详细介绍二叉树的基本概念及其在程序中的实现方法,包括二叉树的创建、遍历(前序、中序、后序)、复制、求高度、判断是否为完全二叉树以及利用二叉树进行表达式的计算等操作。 ### 一、...

    构造二叉树与遍历二叉树

    ### 构造二叉树与遍历二叉树 #### 一、二叉树的基本概念 二叉树(Binary Tree)是一种非线性数据结构,在计算机科学中被广泛应用于各种算法和程序设计中。一个二叉树由零个或多个节点组成,其中每个节点最多有两个子...

    按凹入表形式横向打印任意二叉树结构,即二叉树的根在屏幕的最左边,二叉树的左子树在屏幕的下边,二叉树的右子树在屏幕的上边。

    二叉树横向打印算法的实现 二叉树是一种基本的数据结构,在计算机科学和编程中广泛应用。本资源介绍了一种特殊的二叉树打印算法,即横向打印二叉树结构。该算法将二叉树的根节点放在屏幕的最左边,左子树在屏幕的...

    复制一棵二叉树

    ### 知识点:复制一棵二叉树 #### 一、引言 在计算机科学领域,数据结构中的二叉树是一种常见的非线性数据结构,它由节点组成,每个节点最多有两个子节点,分别称为左子节点和右子节点。复制二叉树是指创建一个与原...

    二叉树的递归算法:建立二叉树、遍历二叉树

    ### 二叉树的递归算法:建立与遍历 #### 一、二叉树的基本概念 二叉树是计算机科学中的一个重要数据结构,它是一种树形结构,其中每个节点最多有两个子节点,通常称为左子节点和右子节点。在二叉树中,左子节点...

    二叉树的基本运算

    建立一棵二叉树,试编程实现二叉树的如下基本操作: 1. 按先序序列构造一棵二叉链表表示的二叉树T; 2. 对这棵二叉树进行遍历:先序、中序、后序以及层次遍历,分别输出结点的遍历序列; 3. 求二叉树的深度/结点数目...

    二叉树相关算法的实验验证+判别给定二叉树是否为完全二叉树。

    1、 定义链接存储的二叉树类。 2、 实验验证如下算法的正确性、各种功能及指标: 1) 创建一棵二叉树,并对其初始化; 2)先根、中根、后根遍历二叉树; 3) 在二叉树中搜索给定结点的父结点; 4) 搜索二叉树中符合...

    二叉树的建立与遍历

    二叉树的建立与遍历 二叉树是一种重要的数据结构,它广泛应用于计算机科学和软件工程中。在这篇文章中,我们将讨论二叉树的建立和遍历,包括先序遍历、中序遍历和后序遍历。 一、数据结构的重要性 数据结构是...

    二叉树_二叉树遍历_

    1.二叉树的基本操作实现【问题描述】建立一棵二叉树,用递归方法实现二叉树的如下基本操作:(1)按先序序列构造一棵二叉链表表示的二叉树T;(2)对这棵二叉树进行遍历:先序、中序、后序以及层次遍历,分别输出...

    求二叉树最大宽度 求二叉树最大宽度 数据结构

    在探讨“求二叉树最大宽度”的数据结构问题时,我们深入分析了如何通过特定算法找到一棵二叉树中每一层节点的最大数量,这一过程涉及到了数据结构与算法设计的关键概念和技术。 ### 一、二叉树的概念 二叉树是一种...

    二叉树模拟器.py二叉树模拟器.py

    二叉树模拟器.py二叉树模拟器.py二叉树模拟器.py二叉树模拟器.py二叉树模拟器.py二叉树模拟器.py二叉树模拟器.py二叉树模拟器.py二叉树模拟器.py二叉树模拟器.py二叉树模拟器.py二叉树模拟器.py二叉树模拟器.py...

    设计程序实现二叉树结点的类型定义和对二叉树的基本操作

    ### 二叉树基本操作知识点解析 #### 一、实验目的 在本实验中,学习者将通过实际编程练习来加深对二叉树这一数据结构的理解,并熟练掌握其基本操作。具体目标包括: 1. **熟悉二叉树结点的结构和对二叉树的基本...

    二叉树遍历实验报告

    ### 二叉树遍历实验报告知识点概览 #### 一、实验背景及目标 **实验背景:** 本次实验属于《数据结构》课程的一部分,旨在通过实际编程加深学生对二叉树这一数据结构的理解和应用能力。二叉树作为一种基本且重要的...

Global site tag (gtag.js) - Google Analytics