排序二叉树及其遍历 c语言实现

    所谓建立排序二叉树就是,就是将各结点数据元素顺序插到一棵二叉树中,在插入的过程中,始终保持二叉树中每个结点的值都大于其左子树上每个结点的值,而小于或等于其右子树上每个结点的值,每个结点信息包括结点数据(结点值)、左子树指针、右子树指针。

程序执行的过程中,bt指针始终指向根结点,p指针指向当前已找到的结点,q指针不断向下寻找新的结点。

   为实现二叉树的非递归算法,需要设置一个栈来保存指向结点的指针,以便在遍历某结点的左子树后,由这个指针能找到该结点的右子树。栈中的地址是随着结点的遍历次序而动态变化的。

   二叉树的结点小于等于2. 插入过程还可以看到,每次插入的新结点都是二叉排序树的新的叶子结点,在进行插入操作时,不必移动其他结点,仅需改动某个结点的指针,由空变为非空即可。

 

以下是参考http://blog.csdn.net/AmiRural/archive/2005/09/12/477834.aspx改写的程序代码,包括了递归的实现和我自己的实现方法。在vc6下调试过了,把代码考下来再看清晰些儿,在这看起来乱七八糟的。

 

参考程序:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <assert.h>

 

#define  MAX       100

#define  INPUT_END -1

#define  ERR       -1

#define  SZ        1024

 

int counter=0;

int stack[MAX],top=0;

 

typedef struct btreenode

{

    int data;

    struct btreenode *lchild;

    struct btreenode *rchild;

}bnode;

 

typedef struct

{

    bnode* vec[MAX];

    int head, tail;

}myque;

 

void push_node(int s)

{

    top++;

    stack[top]=s;

}

 

int pop_node(void)

{

    top--;

    return(stack[top+1]);

}

 

bnode *creat_root(int x)  //建立一个只有根结点的二叉树

{

    bnode *p;

 

    p=(bnode*)malloc (sizeof(bnode));

    if (p != NULL)

    {

        p->data=x;

        p->lchild = NULL;

        p->rchild = NULL;

    }

 

    return(p);

}

 

bnode *inslchild(bnode *p,int x)     //x作为左孩子插入到二叉树中

{

    bnode *q;

 

    if(p==NULL)

    {

       printf("Illegal insert.");

       return NULL;

    }

 

    q = (bnode*)malloc(sizeof(bnode));

    if (q != NULL)

    {

        q->data = x;

        q->lchild=NULL;

        q->rchild=NULL;

        p->lchild=q;  //x做为p <script src="http://hi.images.csdn.net/js/blog/tiny_mce/plugins/syntaxhl/langs/zh.js" type="text/javascript"></script> 的左孩子

    }

 

    return q;

}

 

bnode *insrchild(bnode *p,int x)

{

    bnode *q;

 

    if(p==NULL)

    {

       printf("Illegal insert.");

       return NULL;

    }

 

    q = (bnode*)malloc(sizeof(bnode));

    if (q != NULL)

    {

       q->data=x;

       q->lchild=NULL;

       q->rchild=NULL;    

       p->rchild=q;  //x作为p的右孩子

    }

 

    return q;

}

 

void prorder(bnode *p)     //输出二叉树的结构

{

    if(p==NULL)

    return;

 

    printf("%d/t%u/t%d/t%u/t%u/n",++counter,p,p->data,p->lchild,p->rchild);

    if(p->lchild!=NULL)

       prorder(p->lchild);

    if(p->rchild!=NULL)

       prorder(p->rchild);

}

 

void print(bnode *p)    //嵌套括号表示二叉树,输出左子树前打印左括号,

{                       //输出右子树后打印右括号。

  if(p!=NULL)

  {

    printf("%d",p->data);

    if(p->lchild!=NULL||p->rchild!=NULL)

    {

        printf("(");

        print(p->lchild);

        if(p->rchild!=NULL)

            printf(",");

        print(p->rchild);

        printf(")");

    }

  }

}

 

void preorder(bnode *p)           //前序遍历

{

    while(p!=NULL||top!=0)

    {

        if(p!=NULL)

        {

            printf("%d ",p->data); //输出结点值

            push_node((int)p);         //将指针值压入栈中

            p=p->lchild;          //遍历左子树

        }

        else

        {

            p=(bnode*)pop_node();

            p=p->rchild;          //遍历右子树

        }

    }

}

 

void inorder(bnode *p)           //压栈实现中序遍历

{

    while(p!=NULL||top!=0)              

    {

        while(p!=NULL)

        {

            push_node((int)p);        //将根结点压入栈中

            p=p->lchild;         //遍历左子树

        }

        p=(bnode*)pop_node();

        printf("%d ",p->data);   //输出当前结点值

        p=p->rchild;             //遍历右子树

    }

}

 

void my_preorder_stack(bnode *p)

{

    if (p == NULL)

    {

        return;

    }

 

    top = 0;

    while (p != NULL || top != 0)

    {

        if(p != NULL)

        {

            printf("%d ", p->data);

            push_node((int)p);

            p = p->lchild;

        }

        else

        {

            p = (bnode*)pop_node();

            p = p->rchild;

        }

    }

}

 

void my_inorder_stack(bnode *p)

{

    if (p == NULL)

    {

        return;

    }

 

    top = 0;

    while (p != NULL || top != 0)

    {

        while(p != NULL)

        {

            push_node((int)p);

            p = p->lchild;

        }

        p = (bnode*)pop_node();

        printf("%d ", p->data);

        p = p->rchild;

    }

}

 

void my_postorder_stack(bnode *p) //栈实现后序遍历

{

    bnode *t = NULL;

    top = 0;

 

    if (p == NULL)

    {

        return;

    }

 

    while (p != NULL || top != 0)

    {

        while(p != NULL)

        {

            push_node((int)p);

            p = p->lchild;

        }

        p = (bnode*)pop_node();

 

        //如果右孩子为空或者已经遍历过了,就打印该节点数据

        if (p->rchild == NULL || p->rchild == t) 

        {

            printf("%d ", p->data);

            t = p;

            p = NULL;

        }

        else

        {

            push_node((int)p);

            p = p->rchild;

        }

    }

}

 

void my_inorder(bnode *p) //递归实现中序遍历

{

    if (p == NULL)

    {

        return;

    }

 

    if (p->lchild != NULL)

    {

        inorder(p->lchild);

    }

 

    printf("%d ", p->data);

 

    if (p->rchild != NULL)

    {

        inorder(p->rchild);

    }

}

 

void que_add(myque *q, bnode *p)

{

    /* 当队列满时,头head和尾tail之间总存在一个空闲空间,它是为了区分栈满于栈空 */

    if((q->tail+1)%MAX == q->head) 

    {

        printf("queue overflow!/n");

    }

    else

    {

        q->vec[q->tail] = p;

        q->tail = (q->tail + 1) % MAX;

    }

}

 

bnode* que_del(myque *q)

{

    bnode* p = NULL;

    if (q->tail == q->head)

    {

        printf("nothing for delete!/n");

    }

    else

    {

        p = q->vec[q->head];

        q->head = (q->head + 1) % MAX;

    }

    return p;

}

 

int que_empty(myque *q)

{

    return (q->tail == q->head) ? 1 : 0;

}

 

void my_translevel(bnode *p)

{

    bnode *t;

    myque *q;

 

    if (p == NULL)

    {

        return;

    }

 

    q = (myque*)malloc(sizeof(myque));

    if (q == NULL)

    {

        printf("malloc failure!/n");

    }

    memset(q, 0, sizeof(myque));

 

    que_add(q, p);

    while( !que_empty(q))

    {

        t = que_del(q);

        assert(t!=NULL);

 

        if (t->lchild != NULL)

        {

            que_add(q, t->lchild);

        }

 

        if (t->rchild != NULL)

        {

            que_add(q, t->rchild);

        }

 

        printf("%d ", t->data);

    }

 

    if (q != NULL) //释放内存

    {

        free(q);

        q = NULL;

    }

 

}

 

void my_postorder_recursive(bnode *p)

{

    if (p == NULL)

    {

        return;

    }

 

    if (p->lchild != NULL)

    {

        my_postorder_recursive(p->lchild);

    }

 

    if (p->rchild != NULL)

    {

        my_postorder_recursive(p->rchild);

    }

 

    printf("%d ", p->data);

}

 

void postorder(bnode *p)                //后序遍历

{

    unsigned sign;                      //设置一个标志,记录结点从栈中弹出的次数

 

    while(p!=NULL||top!=0)

    {

        if(p!=NULL)

        {

             push_node((int)p);               //第1次遇到结点p时压入其指针值

             push_node(1);               //置标志为1

             p=p->lchild;                //遍历结点p的左子树

        }

        else

        while(top!=0)

        {

            sign=pop_node();

            p=(bnode*)pop_node();

 

            if(sign==1)                 //sign=1表示仅走过p的左子树

            {

                push_node((int)p);           //第2次压入结点p的指针值

                push_node(2);           //设置标志为2

                p=p->rchild;            //遍历p的右子树

                break;

            }

            else if(sign==2)            //sign=2表示p的左右子树都已走完

            {

                printf("%d ",p->data);  //输出结点p的值

                p=NULL;

            }

        } //while(top!=0)

    } //while(p!=NULL||top!=0)

}

 

void translevel(bnode *p)               //层次遍历

{

    struct node

    {

     bnode *vec[MAX];

     int front,rear;

    }q;

 

    q.front=q.rear=0;

    if(p!=NULL)

      printf("%d ",p->data);

 

    q.vec[q.rear]=p;                       //结点指针进入队列

    q.rear=q.rear+1;

    while(q.front<q.rear)                  //队列不为空

    {

         p=q.vec[q.front];                 //队头出队列

         q.front=q.front+1;

         if(p->lchild!=NULL)               //输出左孩子,并入队列

         {

             printf("%d ",p->lchild->data);

             q.vec[q.rear]=p->lchild;

             q.rear=q.rear+1;

         }

         if(p->rchild!=NULL)

         {

             printf("%d ",p->rchild->data);

             q.vec[q.rear]=p->rchild;

             q.rear=q.rear+1;

         }

    }

}

 

void my_free(bnode *p) // 不要忘记释放内存

{

    if (p == NULL)

    {

        return;

    }

 

    if (p->lchild != NULL)

    {

        my_free(p->lchild);

    }

 

    if (p->rchild != NULL)

    {

        my_free(p->rchild);

    }

 

    free(p);

}

 

int main(int argc, char* argv[])

{

    bnode *r,*p;

    int x=0, y=0;

    int i = 0;

 

    int  a[10] = {10  , -50 , 23, 100, 250, 

                  -40 , 200, 24, 50 , 400};

 

start:

    i = 0;

    while (1)

    {

        printf("Input root:");

        scanf("%d",&x);

        if (x >= 0 && x <=100)

        {

            break;

        }

        else

        {

            printf("The root value need to be in 0 to 100!/n");

        }

    }

 

    r = creat_root(x);

    if (r == NULL)

    {

        printf("Create root node failure!/n");

    }

 

    x = 0;

    printf("Input other node:/n");

 

    while(i<10)

    {

        //scanf("%d",&x);

        x = a[i++];

 

//         if (x == INPUT_END)

//         {

//             break;

//         }

 

        p = r;

        while(1)

        {

            if (x == p->data)

            {

                printf("The node %d  existed already!/n", x);

                break;

            }

            else if (x < p->data)

            {

                if(p->lchild == NULL)

                {

                    inslchild(p, x);

                    break;

                }

                else

                {

                    p = p->lchild;

                }

            }

            else 

            {

                if (p->rchild == NULL)

                {

                    insrchild(p, x);

                    break;

                }

                else

                {

                    p = p->rchild;

                }

            }

        }

    }

 

    p=r;

    printf("structure of the binary tree:/n");

    printf("number/taddress/tdata/tlchild/trchild/n");

    prorder(p);

    printf("/n");

    print(p);

 

    printf("/t输出左子树前打印左括号,输出右子树后打印右括号。/n");

    printf("----------1 前序遍历二叉树---------- /n");

    printf("----------2 中序遍历二叉树---------- /n");

    printf("----------3 后序遍历二叉树---------- /n");

    printf("----------4 层次遍历二叉树---------- /n");

    printf("----------5 退出程序---------------- /n");

 

    while (1)

    {

        printf("请选择遍历方式:");

        scanf("%d",&x);

        if (x == 5)

        {

            my_free(p);

            break;

        }

 

        switch(x)

        {

        case 1:

            preorder(p);

            printf("/n");

            break;

        case 2:

            inorder(p);

            printf("/n");

            break;

        case 3:

            postorder(p);

            //printf("/n");

            //my_postorder_stack(p);

            //my_postorder_recursive(p);

            printf("/n");

            break;

        case 4:

            translevel(p);

            printf("/n");

            my_translevel(p);

            printf("/n");

            break;

        default:

            my_free(p);

            goto start;

        }

    }

 

    return 0;

}       

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值