1. 程式人生 > 實用技巧 >區間染色_浮水法_洛谷_P3740貼海報

區間染色_浮水法_洛谷_P3740貼海報

這個作業屬於哪個課程 https://edu.cnblogs.com/campus/qdu/DS2020
這個作業要求在哪裡 https://edu.cnblogs.com/campus/qdu/DS2020/homework/11430
這個作業的目標 掌握二叉樹
學號 2018204186

一、實驗目的
1、掌握二叉樹的基本特性
2、掌握二叉樹的先序、中序、後序的遞迴遍歷演算法
3、理解二叉樹的先序、中序、後序的非遞迴遍歷演算法
4、通過求二叉樹的深度、葉子結點數和層序遍歷等演算法,理解二叉樹的基本特性

二、實驗預習
說明以下概念
1、二叉樹:在電腦科學中,樹是一種重要的非線性資料結構,直觀的看,它是資料元素按分支關係組織起來的結構。二叉樹是每個節點最多有兩個子樹的有序樹,通常子樹的根被稱作“左子樹”和“右子樹”。

2、遞迴遍歷:遍歷:所謂遍歷(Traversal),是指沿著某條搜尋路線,依次對樹(或圖)中每個節點均做一次訪問。訪問結點所做的操作依賴於具體的應用問題, 具體的訪問操作可能是檢查節點的值、更新節點的值等。不同的遍歷方式,其訪問節點的順序是不一樣的。遍歷是二叉樹上最重要的運算之一,是二叉樹上進行其它運算之基礎。當然遍歷的概念也適合於多元素集合的情況。
遞迴:程式呼叫自身的程式設計技巧稱為遞迴。

3、 非遞迴遍歷:不採用遞迴的方式對二叉樹進行遍歷。

4、層序遍歷:就是按層,從上到下,從左到右遍歷。

三、實驗內容和要求
1、閱讀並執行下面程式,根據輸入寫出執行結果,並畫出二叉樹的形態。

#include<stdio.h>
#include<malloc.h>
#include<iostream>
#include<conio.h>
#define MAX 20
typedef struct BTNode{       /*節點結構宣告*/
	char data ;               /*節點資料*/
	struct BTNode *lchild;
	struct BTNode *rchild ;  /*指標*/
}*BiTree;

void createBiTree(BiTree *t){ /* 先序遍歷建立二叉樹*/
	char s;
	BiTree q;
	printf("\nplease input data:(exit for #)");
	s=getche();
	if(s=='#'){*t=NULL; return;}
	q=(BiTree)malloc(sizeof(struct BTNode));
	if(q==NULL){printf("Memory alloc failure!"); exit(0);}
	q->data=s;
	*t=q;
	createBiTree(&q->lchild); /*遞迴建立左子樹*/
	createBiTree(&q->rchild); /*遞迴建立右子樹*/
}

void PreOrder(BiTree p){  /* 先序遍歷二叉樹*/
    if ( p!= NULL ) {
       	printf("%c", p->data);
       	PreOrder( p->lchild ) ;
       	PreOrder( p->rchild) ;
    }
}
void InOrder(BiTree p){  /* 中序遍歷二叉樹*/
    if( p!= NULL ) {
 	 InOrder( p->lchild ) ;
   	 printf("%c", p->data);
   	 InOrder( p->rchild) ;
    }
}
void PostOrder(BiTree p){  /* 後序遍歷二叉樹*/
   if ( p!= NULL ) {
    	PostOrder( p->lchild ) ;
       	PostOrder( p->rchild) ;
       	printf("%c", p->data);
    }
}

void Preorder_n(BiTree p){ /*先序遍歷的非遞迴演算法*/
    BiTree stack[MAX],q;
    int top=0,i;
    for(i=0;i<MAX;i++) stack[i]=NULL;/*初始化棧*/
    q=p;
    while(q!=NULL){
        printf("%c",q->data);
        if(q->rchild!=NULL) stack[top++]=q->rchild;
        if(q->lchild!=NULL) q=q->lchild;
        else
            if(top>0) q=stack[--top];
            else q=NULL;
    }
}

void release(BiTree t){ /*釋放二叉樹空間*/
  	if(t!=NULL){
    	release(t->lchild);
    	release(t->rchild);
    	free(t);
  	}
}

int main(){
    BiTree t=NULL;
    createBiTree(&t);
    printf("\n\nPreOrder the tree is:");
    PreOrder(t);
    printf("\n\nInOrder the tree is:");
    InOrder(t);
    printf("\n\nPostOrder the tree is:");
    PostOrder(t);
    printf("\n\n先序遍歷序列(非遞迴):");
    Preorder_n(t);
    release(t);
    return 0;
}

執行程式
輸入:
ABC##DE#G##F###
執行結果:

2、在上題中補充求二叉樹中求結點總數演算法(提示:可在某種遍歷過程中統計遍歷的結點數),並在主函式中補充相應的呼叫驗證正確性。
演算法程式碼:

int PreOrder_num(BiTree p) {

	int j=0;

	BiTree stack[MAX],q;

	int top=0,i;

	for(i=0; i<MAX; i++) stack[i]=NULL; /*初始化棧*/

	q=p;

	while(q!=NULL) {

		j++;
		
		if(q->rchild!=NULL) stack[top++]=q->rchild;

		if(q->lchild!=NULL) q=q->lchild;

		else

			if(top>0) q=stack[--top];

			else q=NULL;

	}

    return j;

}

執行結果:

3、在上題中補充求二叉樹中求葉子結點總數演算法(提示:可在某種遍歷過程中統計遍歷的葉子結點數),並在主函式中補充相應的呼叫驗證正確性。

演算法程式碼:

int BTNodeDepth(BiTree p) {

	int lchilddep,rchilddep;

	if(p==NULL)

		return 0;

	else {

		lchilddep=BTNodeDepth(p->lchild);

		rchilddep=BTNodeDepth(p->rchild);

		return(lchilddep>rchilddep)?(lchilddep+1):(rchilddep+1);
	}
}

執行結果:

選做實驗:(程式碼可另附紙)
4、 補充二叉樹層次遍歷演算法。(提示:利用佇列實現)

#include<stdio.h>
#include<stdlib.h>
 
typedef char EType;
 
struct BinaryTreeNode//定義節點
{  
    EType data;  
    struct BinaryTreeNode *LChild;  
    struct BinaryTreeNode *RChild;  
};  
typedef BinaryTreeNode BinaryTree; 
 
typedef struct QType  
{  
    BinaryTreeNode *ptr;
}QType; 
 
typedef struct Queue
{
	QType *element;//迴圈線性佇列,0號空間不使用(為了區分隊滿與隊空),注意這不是鏈式佇列
	int front;
	int rear;
	int MaxSize;
}Queue;
 
void CreatBiTree(BinaryTreeNode **BT);
bool IsEmpty(Queue &Q);
bool IsFull(Queue &Q);
bool GetFront(Queue &Q,QType &result);
bool EnQueue(Queue &Q,QType &x);
bool DeQueue(Queue &Q,QType &result);
void LevelOrder_LtoR_UtoD(BinaryTreeNode *BT);
void LevelOrder_RtoL_UtoD(BinaryTreeNode *BT);
 
int main()
{
	BinaryTreeNode *BT = NULL;
	CreatBiTree(&BT);
	printf("從上至下,從左至右遍歷二叉樹輸出為:");
	LevelOrder_LtoR_UtoD(BT);
	printf("\n");
	printf("從上至下,從右至左遍歷二叉樹輸出為:");
	LevelOrder_RtoL_UtoD(BT);
	printf("\n");
	return 0;
}
 
void CreatQueue(Queue &Q,int MaxQueueSize)
{
	Q.MaxSize = MaxQueueSize;
	Q.element = new QType[Q.MaxSize+1];
	Q.front = 0;
	Q.rear = 0;
}
 
bool IsEmpty(Queue &Q)
{
	if(Q.front == Q.rear)
		return true;
	return false;
}
 
bool IsFull(Queue &Q)
{
	if(Q.front == (Q.rear+1)%(Q.MaxSize+1))
		return true;
	return false;
}
 
bool GetFront(Queue &Q,QType &result)
{
	if(IsEmpty(Q))
		return false;
	result = Q.element[(Q.front+1)%(Q.MaxSize+1)];
	return true;
}
 
bool EnQueue(Queue &Q,QType &x)//進隊操作:rear向後移
{
	if(IsFull(Q))
		return false;
	Q.rear = (Q.rear+1)%(Q.MaxSize+1);
	Q.element[Q.rear] = x;
	return true;
}
 
bool DeQueue(Queue &Q,QType &result)//出隊操作:front向後移
{
	if(IsEmpty(Q))
		return false;
	Q.front = (Q.front+1)%(Q.MaxSize+1);
	result = Q.element[Q.front];
	return true;
}
 
void CreatBiTree(BinaryTreeNode **BT)//以前序遍歷方法輸入節點的data,構造一棵二叉樹
{  
    EType tem;  
      
    scanf("%c",&tem);  
    if(' ' == tem)  
    {  
        *BT = NULL;  
    }  
    else  
    {  
        *BT = new BinaryTreeNode;  
        (*BT)->data = tem;  
        CreatBiTree(&(*BT)->LChild);//遞迴
        CreatBiTree(&(*BT)->RChild);  
    }  
}  
 
void LevelOrder_LtoR_UtoD(BinaryTreeNode *BT)
{
	Queue Q;
	QType temp;
	BinaryTreeNode *p;
	int MaxQueueSize = 50;
	CreatQueue(Q,MaxQueueSize);
	p = BT;
	temp.ptr = p;
	EnQueue(Q,temp);//先將根節點進隊
	while(p)//二叉樹為空就直接結束
	{
		if(!DeQueue(Q,temp))//節點出隊,當隊空時,出隊操作返回false,程式return
			return;//這是這個迴圈的出口,如果一個二叉樹不為空,最終都是在這裡跳出迴圈
		p = temp.ptr;
		printf("%c\t",p->data);
 
		if(p->LChild)//若該節點的左孩子存在,則將其進隊
		{
			temp.ptr = p->LChild;
			EnQueue(Q,temp);
		}
        if(p->RChild)//若該節點的右孩子存在,則將其進隊
		{
			temp.ptr = p->RChild;
			EnQueue(Q,temp);
		}
	}
}
 
void LevelOrder_RtoL_UtoD(BinaryTreeNode *BT)
{
    Queue Q;
	QType temp;
	BinaryTreeNode *p;
	int MaxQueueSize = 50;
	CreatQueue(Q,MaxQueueSize);
	p = BT;
	temp.ptr = p;
	EnQueue(Q,temp);
	while(p)
	{
		if(!DeQueue(Q,temp))
			return;
		p = temp.ptr;
		printf("%c\t",p->data);
 
		if(p->RChild)
		{
			temp.ptr = p->RChild;
			EnQueue(Q,temp);
		}
		if(p->LChild)
		{
			temp.ptr = p->LChild;
			EnQueue(Q,temp);
		}
	}
}

執行結果:

5、補充二叉樹中序、後序非遞迴演算法。

/*二叉樹的遍歷* 2011.8.25*/

#include <iostream>
#include<string.h>
#include<stack>
#include<stdlib.h>
using namespace std;

typedef struct node
{
    char data;
    struct node *lchild,*rchild;
}BinTree;

typedef struct node1
{
    BinTree *btnode;
    bool isFirst;
}BTNode;


void creatBinTree(char *s,BinTree *&root)  //建立二叉樹,s為形如A(B,C(D,E))形式的字串
{
    int i;
    bool isRight=false;
    stack<BinTree*> s1;          //存放結點
    stack<char> s2;              //存放分隔符
    BinTree *p,*temp;
    root->data=s[0];
    root->lchild=NULL;
    root->rchild=NULL;
    s1.push(root);
    i=1;
    while(i<strlen(s))
    {
        if(s[i]=='(')
        {
            s2.push(s[i]);
            isRight=false;
        }
        else if(s[i]==',')
        {
            isRight=true;
        }
        else if(s[i]==')')
        {
            s1.pop();
            s2.pop();
        }
        else if(isalpha(s[i]))
        {
            p=(BinTree *)malloc(sizeof(BinTree));
            p->data=s[i];
            p->lchild=NULL;
            p->rchild=NULL;
            temp=s1.top();
            if(isRight==true)
            {
                temp->rchild=p;
                cout<<temp->data<<"的右孩子是"<<s[i]<<endl;
            }
            else
            {
                temp->lchild=p;
                cout<<temp->data<<"的左孩子是"<<s[i]<<endl;
            }
            if(s[i+1]=='(')
                s1.push(p);
        }
        i++;
    }
}

void display(BinTree *root)        //顯示樹形結構
{
    if(root!=NULL)
    {
        cout<<root->data;
        if(root->lchild!=NULL)
        {
            cout<<'(';
            display(root->lchild);
        }
        if(root->rchild!=NULL)
        {
            cout<<',';
            display(root->rchild);
            cout<<')';
        }
    }
}

void preOrder1(BinTree *root)     //遞迴前序遍歷
{
    if(root!=NULL)
    {
        cout<<root->data<<" ";
        preOrder1(root->lchild);
        preOrder1(root->rchild);
    }
}

void inOrder1(BinTree *root)      //遞迴中序遍歷
{
    if(root!=NULL)
    {
        inOrder1(root->lchild);
        cout<<root->data<<" ";
        inOrder1(root->rchild);
    }
}

void postOrder1(BinTree *root)    //遞迴後序遍歷
{
    if(root!=NULL)
    {
        postOrder1(root->lchild);
        postOrder1(root->rchild);
        cout<<root->data<<" ";
    }
}

void preOrder2(BinTree *root)     //非遞迴前序遍歷
{
    stack<BinTree*> s;
    BinTree *p=root;
    while(p!=NULL||!s.empty())
    {
        while(p!=NULL)
        {
            cout<<p->data<<" ";
            s.push(p);
            p=p->lchild;
        }
        if(!s.empty())
        {
            p=s.top();
            s.pop();
            p=p->rchild;
        }
    }
}

void inOrder2(BinTree *root)      //非遞迴中序遍歷
{
    stack<BinTree*> s;
    BinTree *p=root;
    while(p!=NULL||!s.empty())
    {
        while(p!=NULL)
        {
            s.push(p);
            p=p->lchild;
        }
        if(!s.empty())
        {
            p=s.top();
            cout<<p->data<<" ";
            s.pop();
            p=p->rchild;
        }
    }
}

void postOrder2(BinTree *root)    //非遞迴後序遍歷
{
    stack<BTNode*> s;
    BinTree *p=root;
    BTNode *temp;
    while(p!=NULL||!s.empty())
    {
        while(p!=NULL)              //沿左子樹一直往下搜尋,直至出現沒有左子樹的結點
         {
            BTNode *btn=(BTNode *)malloc(sizeof(BTNode));
            btn->btnode=p;
            btn->isFirst=true;
            s.push(btn);
            p=p->lchild;
        }
        if(!s.empty())
        {
            temp=s.top();
            s.pop();
            if(temp->isFirst==true)     //表示是第一次出現在棧頂
             {
                temp->isFirst=false;
                s.push(temp);
                p=temp->btnode->rchild;
            }
            else                        //第二次出現在棧頂
             {
                cout<<temp->btnode->data<<" ";
                p=NULL;
            }
        }
    }
}

void postOrder3(BinTree *root)     //非遞迴後序遍歷
{
    stack<BinTree*> s;
    BinTree *cur;                      //當前結點
    BinTree *pre=NULL;                 //前一次訪問的結點
    s.push(root);
    while(!s.empty())
    {
        cur=s.top();
        if((cur->lchild==NULL&&cur->rchild==NULL)||
           (pre!=NULL&&(pre==cur->lchild||pre==cur->rchild)))
        {
            cout<<cur->data<<" ";  //如果當前結點沒有孩子結點或者孩子節點都已被訪問過
              s.pop();
            pre=cur;
        }
        else
        {
            if(cur->rchild!=NULL)
                s.push(cur->rchild);
            if(cur->lchild!=NULL)
                s.push(cur->lchild);
        }
    }
}


int main(int argc, char *argv[])
{
    char s[100];
    while(scanf("%s",s)==1)
    {
        BinTree *root=(BinTree *)malloc(sizeof(BinTree));
        creatBinTree(s,root);
        display(root);
        cout<<endl;
        preOrder2(root);
        cout<<endl;
        inOrder2(root);
        cout<<endl;
        postOrder2(root);
        cout<<endl;
        postOrder3(root);
        cout<<endl;
    }
    return 0;
}```

四、實驗小結

五、評語