數據機構實驗報告-實驗三 二叉樹基本操作的實現


實驗三   二叉樹基本操作的實現

 

實驗目的

1、二叉樹的基本操作

(1)掌握二叉樹鏈表的結構和二叉排序樹的建立過程。

(2)掌握二叉樹排序樹的插入和刪除操作。

(3)加深對二叉樹的理解,逐步培養解決實際問題的編程能力。

2、樹的遍歷和哈夫曼樹

(1)掌握用遞歸方法實現二叉樹遍歷的操作。

(2)掌握用非遞歸方法實現二叉樹遍歷的操作。

(3)掌握建立Huffman樹的操作。

(4)加深對二叉樹的理解,逐步培養解決實際問題的編程能力。

實驗內容

1、二叉樹的基本操作

(一)基礎題

(1)SearchNode(TREE *tree,int key,TREE **pkpt,TREE **kpt)查找結點函數;

(2)InsertNode(TREE **tree,int key)二叉排序樹插入函數;

(3)DeleteNode(TREE **tree,int key)二叉排序樹刪除函數;

2.調用上述函數實現下列操作:

(1)初始化一棵二叉樹;

(2)調用插入函數建立一棵二叉排序樹;

(3)調用查找函數在二叉樹中查找指定的結點;

(二)提高題

【問題描述】已知以二叉樹鏈表作為存儲結構,試編寫按中序遍歷並打印二叉樹的算法。

【程序設計思路】采用一個棧,先將二叉樹的根結點入棧,若它有左子樹,便將左子樹的根節點入棧,直到左子樹為空,然后依次退棧並輸出結點值;若輸出的結點有右子樹,便將右子樹的根結點入棧,如此循環入棧、退棧,直到棧為空為止。

 

2、樹的遍歷和哈夫曼樹

(1)re_preorder(TREE *tree) 先序遍歷,采用遞歸方法;

(2)re_midorder(TREE *tree)中序遍歷,采用遞歸方法;

(3)re_posorder(TREE *tree) 后序遍歷,采用遞歸方法;

(4)st_preorder(TREE *tree)先序遍歷,采用鏈接棧的迭代方法;

(5)st_midorder(TREE *tree)中序遍歷,采用鏈接棧的迭代方法;

(6)st_posorder(TREE *tree)后序遍歷,采用鏈接棧的迭代方法;

2.調用上述函數實現下列操作:

(1)用遞歸方法分別實現先序、中序和后序遍歷二叉樹;

(2)用非遞歸方法分別實現先序、中序和后序遍歷二叉樹。

(3)程序源代碼

#include<stdio.h>

#include<malloc.h>

#include<conio.h>

#include <windows.h>

#include<stdlib.h>

typedef struct tree /* 定義樹的結構*/

{

    int data;              /*假定樹的元素類型為int*/

    struct tree *lchild;   /*左孩子*/

    struct tree *rchild;   /*右孩子*/

}TREE;

typedef struct stack /*定義鏈接棧結構*/

{

    TREE *t;   /*棧結點元素為指向二叉樹結點的指針*/

    int flag;  /*后序遍歷時用到該標志*/

    struct stack *link;/*棧結點鏈接指針*/

}STACK;

void gotoxy(int x,int y)    //x為列坐標,y為行坐標

{

    COORD pos={x,y};    //設定坐標

    HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);    //函數句柄

    SetConsoleCursorPosition(hOut,pos);

}

void push(STACK **top,TREE *tree)/*樹結點入棧*/

{

    STACK *p;   /*工作指針*/

    p=(STACK*)malloc(sizeof(STACK));/*申請棧結點*/

    p->t=tree;   /*根結點進棧*/

    p->link=*top; /*新棧結點指向棧頂*/

    *top=p;  /*棧頂為新結點*/

}

void pop(STACK **top,TREE **tree)/*出棧*/

{

    STACK *p;

    if(*top==NULL)

        *tree=NULL;

    else

    {

        *tree=(*top)->t;

        p=*top;

        *top=(*top)->link;

        free(p);

    }

}

void SearchNode(TREE *tree,int key,TREE **pkpt,TREE **kpt)/*查找樹的根結點*/

{

    *pkpt=NULL;

    *kpt=tree;

    while(*kpt!=NULL)

    {

        if((*kpt)->data==key)

            return;

        *pkpt=*kpt;

        if(key<(*kpt)->data)

            *kpt=(*kpt)->lchild;

        else

            *kpt=(*kpt)->rchild;

    }

}

int InsertNode(TREE **tree,int key) /*在查找樹上插入新結點,返回1表示該鍵值結點已存在,返回-1表示內存申請失敗*/

{

    TREE *p,*q,*r;

    SearchNode(*tree,key,&p,&q);

    if(q!=NULL)

        return 1;

        if((r=(TREE*)malloc(sizeof(TREE)))==NULL)

            return -1;

        r->data=key;

        r->lchild=r->rchild=NULL;

        if(p==NULL)

            *tree=r;

        else if(p->data>key)

            p->lchild=r;

        else

            p->rchild=r;

        return 0;

}

int DeleteNode(TREE **tree,int key) /*在查找樹上刪除結點,返回1表示該鍵值結點不存在*/

{

    TREE *p,*q,*r;

    SearchNode(*tree,key,&p,&q);

    if(q==NULL)

        return 1;

    if(p==NULL)

        if(q->lchild==NULL)

        *tree=q->rchild;

    else

    {

        *tree=q->lchild;

        r=q->lchild;

        while(r->rchild!=NULL)

            r=r->rchild;

        r->rchild=q->rchild;

    }

    else if(q->lchild==NULL)

        if(q==p->lchild)

        p->lchild=q->rchild;

    else

        p->rchild=q->rchild;

    else

    {

        r=q->lchild;

        while(r->rchild!=NULL)

            r=r->rchild;

        r->rchild=q->rchild;

        if(q==p->lchild)

            p->lchild=q->lchild;

        else

            p->rchild=q->lchild;

    }

    free(q);

    return 0;

}

void OutputTree(TREE *tree) /*層次打印樹結點,中序遍歷,采用鏈接棧的迭代方法*/

{

    STACK *top;

    int deep=0,no=0,maxdeep=0;

    top=NULL;

    while(tree!=NULL||top!=NULL)

    {

        while(tree!=NULL)

        {

            push(&top,tree);

            top->flag=++deep;

            if(maxdeep<deep)

                maxdeep=deep;

            tree=tree->lchild;

        }

        if(top!=NULL)

        {

            deep=top->flag;

            no++;

            pop(&top,&tree);

            gotoxy(no *4,deep+2);

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

            fflush(stdout);

            tree=tree->rchild;

        }

    }

    gotoxy(1,maxdeep+3);

    printf("任意鍵繼續\n");

    getch();

}

 

int main()

{

    TREE *t;

    int op=-1,i,ret;

    t=NULL;

    while(op!=0)

    {

        printf("請選擇操作:\n-1-:增加樹結點\n-2-:刪除樹結點\n-0-:結束操作\n");

        fflush(stdin);

        scanf("%d",&op);

        switch(op)

        {

        case 0:

            break;

        case 1:

            printf("請輸入樹結點元素:");

            scanf("%d",&i);

            switch(InsertNode(&t,i))

            {

                case 0:

 

                    system("cls");

                    gotoxy(1,1);

                    printf("成功,樹結構為:\n");

                    OutputTree(t);

                break;

                case 1:

                    printf("該元素已存在");

                    break;

                default:

                    printf("內存操作失敗");

                    break;

            }

            break;

        case 2:

            printf("請輸入要刪除的樹結點元素:");

            scanf("%d",&i);

           if(DeleteNode(&t,i)){

                       system("cls");

                    gotoxy(1,1);

                    printf("刪除成功,樹結構為:\n");

                    OutputTree(t);

               }

           else

            printf("該鍵植樹結點不存在\n");

        break;

    }

}

}
View Code

 

(二)提高題

(1)程序源代碼:

#include<stdio.h>

#include<malloc.h>

#include<conio.h>

#include <windows.h>

#include<stdlib.h>

typedef struct tree

{

    int data;

    struct tree *lchild;

    struct tree *rchild;

}TREE;

typedef struct stack

{

    TREE *t;

    int flag;

    struct stack *link;

}STACK;

void gotoxy(int x,int y)    //x為列坐標,y為行坐標

{

    COORD pos={x,y};    //設定坐標

    HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);    //函數句柄

    SetConsoleCursorPosition(hOut,pos);

}

void push(STACK **top,TREE *tree)

{

    STACK *p;

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

    p->t=tree;

    p->link=*top;

    *top=p;

}

void pop(STACK **top,TREE **tree)

{

    STACK *p;

    if(*top==NULL)

        *tree=NULL;

    else

    {

        *tree=(*top)->t;

        p=*top;

        *top=(*top)->link;

        free(p);

    }

}

void OutputTree(TREE *tree)

{

    STACK *top;

    int deep=0,no=0,maxdeep=0;

    top=NULL;

    while(tree!=NULL||top!=NULL)

    {

        while(tree!=NULL)

        {

            push(&top,tree);

            top->flag=++deep;

            if(maxdeep<deep)

                maxdeep=deep;

            tree=tree->lchild;

        }

        if(top!=NULL)

        {

            deep=top->flag;

            no++;

            pop(&top,&tree);

            gotoxy(no *4,deep+2);

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

            fflush(stdout);

            tree=tree->rchild;

        }

    }

    gotoxy(1,maxdeep+3);

    printf("任意鍵繼續\n");

    getch();

}

2、樹的遍歷和哈夫曼樹

(1)畫出數據結構基本運算的流程圖

 
      
 

 

 

 

 

 

 

 

 

(2)程序運行主要結果截圖

 

 

 

 

 

   

 

 

 

 

(3)程序源代碼

#include<stdio.h>

#include<malloc.h>

#include<conio.h>

#include <windows.h>

#include<stdlib.h>

typedef struct tree /*定義樹結構*/

{

    int data;

    struct tree *lchild;

    struct tree *rchild;

}TREE;

typedef struct stack /*定義鏈接棧結構*/

{

    TREE *t;

    int flag;

    struct stack *link;

}STACK;

void re_preorder(TREE *tree) /*先序遍歷,采用遞歸方法*/

{

    if(tree!=NULL)

    {

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

        re_preorder(tree->lchild);

        re_preorder(tree->rchild);

    }

}

void re_midorder(TREE *tree) /*中序遍歷,采用遞歸方法*/

{

    if(tree!=NULL)

    {

        re_midorder(tree->lchild);

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

        re_midorder(tree->rchild);

    }

}

void re_posorder(TREE *tree) /*后序遍歷,采用遞歸方法*/

{

    if(tree!=NULL)

    {

        re_posorder(tree->lchild);

        re_posorder(tree->rchild);

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

    }

}

void push(STACK **top,TREE *tree)/*樹結點入棧*/

{

    STACK *p;

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

    p->t=tree;

    p->link=*top;

    *top=p;

}

void pop(STACK **top,TREE **tree)/*出棧,棧內元素賦值給樹結點*/

{

    STACK *p;

    if(*top==NULL)

        *tree=NULL;

    else

    {

        *tree=(*top)->t;

        p=*top;

        *top=(*top)->link;

        free(p);

    }

}

void st_preorder(TREE *tree)/*先序遍歷,采用鏈接棧的迭代方法*/

{

    STACK *top;

    top=NULL;

    while(tree!=NULL)

    {

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

        if(tree->rchild!=NULL)

            push(&top,tree->rchild);

        if(tree->lchild!=NULL)

            push(&top,tree->lchild);

        push(&top,tree->lchild);

        pop(&top,&tree);

    }

}

void st_midorder(TREE *tree)/*中序遍歷,采用鏈接棧的迭代方法*/

{

    STACK *top;

    top=NULL;

    while(tree!=NULL||top!=NULL)

    {

        while(tree!=NULL)

        {

            push(&top,tree);

            tree=tree->lchild;

        }

        if(top!=NULL)

        {

            pop(&top,&tree);

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

            tree=tree->rchild;

        }

    }

}

void st_posorder(TREE *tree)/*后序遍歷,采用鏈接棧的迭代方法*/

{

    STACK *top;

    top=NULL;

    do{

        while(tree!=NULL){

            push(&top,tree);

            top->flag=0;

            tree=tree->lchild;

        }

        if(top!=NULL)

        {

            while(top!=NULL&&top->flag==1){

                pop(&top,&tree);

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

            }

            if(top!=NULL)

            {

                top->flag=1;

                tree=(top->t)->rchild;

            }

        }

    }while(top!=NULL);

}

void SearchNode(TREE *tree,int key,TREE **pkpt,TREE **kpt)/*查找樹根結點*/

{

    *pkpt=NULL;

    *kpt=tree;

    while(*kpt!=NULL)

    {

        if((*kpt)->data==key)

            return;

        *pkpt=*kpt;

        if(key<(*kpt)->data)

            *kpt=(*kpt)->lchild;

        else

            *kpt=(*kpt)->rchild;

    }

}

int InsertNode(TREE **tree,int key)/*在查找樹上插入新結點*/

{

    TREE *p,*q,*r;

    SearchNode(*tree,key,&p,&q);

    if(q!=NULL)

        return 1;

        if((r=(TREE*)malloc(sizeof(TREE)))==NULL)

            return -1;

        r->data=key;

        r->lchild=r->rchild=NULL;

        if(p==NULL)

            *tree=r;

        else if(p->data>key)

            p->lchild=r;

        else

            p->rchild=r;

        return 0;

}

void gotoxy(int x,int y)    //x為列坐標,y為行坐標

{

    COORD pos={x,y};    //設定坐標

    HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);    //函數句柄

    SetConsoleCursorPosition(hOut,pos);

}

void OutPutTree(TREE *tree)/*層次打印樹結點,*/

{

    STACK *top;

    int deep=0,no=0,maxdeep=0;

    top=NULL;

    while(tree!=NULL||top!=NULL)

    {

        while(tree!=NULL)

        {

            push(&top,tree);

            top->flag=++deep;

            if(maxdeep<deep)

                maxdeep=deep;

            tree=tree->lchild;

        }

        if(top!=NULL)

        {

            deep=top->flag;

            no++;

            pop(&top,&tree);

            gotoxy(no *4,deep+2);

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

            fflush(stdout);

            tree=tree->rchild;

        }

    }

    gotoxy(1,maxdeep+3);

    printf("任意鍵繼續\n");

    getch();

}

 

int main()

{

    TREE *t;

    int i,op=-1;

    t=NULL;

    while(op!=0)

    {

        printf("請選擇操作:\n-1-:增加數結點;\n-0-:結束操作\n");

        fflush(stdin);

        scanf("%d",&op);

        switch(op)

    {

      case 0:

        break;

      case 1:

        printf("請輸入樹結點元素:");

        scanf("%d",&i);

        switch(InsertNode(&t,i))

        {

            case 0:

            system("cls");

            gotoxy(1,1);

            printf("成功,數據結構為:\n");

            OutPutTree(t);

            break;

            case 1:

                printf("該元素已存在");

                break;

            default:

                printf("內存操作失敗");

                break;

        }

        break;

        }

    }

    printf("先序遍歷,遞歸方法\n");

    re_preorder(t);

    printf("\n任意鍵繼續\n\n");

    getch();

    printf("中序遍歷,遞歸方法\n");

    re_midorder(t);

    printf("\n任意鍵繼續\n\n");

    getch();

    printf("后序遍歷,遞歸方法\n");

    re_posorder(t);

    printf("\n任意鍵繼續\n\n");

    getch();

    printf("先序遍歷,采用鏈接棧的迭代方法\n");

    st_preorder(t);

    printf("\n任意鍵繼續\n\n");

    getch();

    printf("中序遍歷,采用鏈接棧的迭代方法\n");

    st_midorder(t);

    printf("\n任意鍵繼續\n\n");

    getch();

    printf("后序遍歷,采用鏈接棧的迭代方法\n");

    st_posorder(t);

    printf("\n任意鍵繼續\n\n");

    getch();

 

}

 
View Code

 

小結

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM