數據結構——樹的相關算法實現


二叉樹的基本算法

包括二叉樹的遍歷(先、中、后),二叉樹的層次,二叉樹的深度,二叉樹的葉子節點數計算。相關算法思想可以看書,這里只是給出相關算法實現。

代碼實現

#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 30

typedef char ElemType;

typedef struct TNode {
	char data;
	TNode * lchild; 
	TNode * rchild;
}TNode, *BiTree;


int IsEmpty_BiTree(BiTree *T) {
	if(*T == NULL)
	return 1;//如果樹為空一直進入死循環,直到輸入數據為止 
	else
	return 0;
}

void Create_BiTree(BiTree *T){
    char ch;
    ch = getchar();
    //當輸入的是"#"時,認為該子樹為空
    if(ch == '#')
        *T = NULL;
    //創建樹結點
    else{
        *T = (BiTree)malloc(sizeof(struct TNode));
        (*T)->data = ch; //生成樹結點
        //生成左子樹
        Create_BiTree(&(*T)->lchild);
        //生成右子樹
        Create_BiTree(&(*T)->rchild);
    }
}

void TraverseBiTree(BiTree T) {	//先序遍歷 
	if(T == NULL)//指針為空,說明節點不存在 
	return; 
	else {
		printf("%c ",T->data);
		TraverseBiTree(T->lchild);
		TraverseBiTree(T->rchild);
	}
	
}

void InOrderBiTree(BiTree T) {		//中序遍歷 
	if(NULL == T)
	return;
	else {
		InOrderBiTree(T->lchild);
		printf("%c ",T->data);
		InOrderBiTree(T->rchild);	
	}
}

void PostOrderBiTree(BiTree T) {
	if(NULL == T)
	return;
	else {
		InOrderBiTree(T->lchild);
		InOrderBiTree(T->rchild);
		printf("%c ",T->data);
	}
	
} 

int TreeDeep(BiTree T) {
	int deep = 0;
	if(T)
	{
		int leftdeep = TreeDeep(T->lchild);
		int rightdeep = TreeDeep(T->rchild);
		deep = leftdeep+1 > rightdeep+1 ? leftdeep+1 : rightdeep+1; 
	}
	return deep;
}
//樹的葉子結點為 
int Leafcount(BiTree T, int &num) {//一般涉及到變化的都會取地址 
	if(T)
	{
		if(T->lchild ==NULL && T->rchild==NULL)	
		{
			num++;
			printf("%c ",T->data);
		}			
		Leafcount(T->lchild,num);
		Leafcount(T->rchild,num);

	}
	return num;
}

//樹的層次顯示 (利用隊列,先進先出的原則可以完美實現) 
void LevelOrder_BiTree(BiTree T){
    //用一個隊列保存結點信息,這里的隊列采用的是順序隊列中的數組實現
    int front = 0;
    int rear = 0;
    BiTree BiQueue[MAXSIZE];
    BiTree tempNode;
    if(!IsEmpty_BiTree(&T)){
        BiQueue[rear++] = T;
         
        while(front != rear){// 
            //取出隊頭元素,並使隊頭指針向后移動一位 
            tempNode = BiQueue[front++];
            //判斷左右子樹是否為空,若不為空,則加入隊列 
            if(!IsEmpty_BiTree(&(tempNode->lchild)))
                BiQueue[rear++] = tempNode->lchild;
             
            if(!IsEmpty_BiTree(&(tempNode->rchild)))
                BiQueue[rear++] = tempNode->rchild;
             
             printf("%c ",tempNode->data);
        }
    }
}

int main(void)
{
	BiTree T;
	BiTree *p = (BiTree*)malloc(sizeof(BiTree));
	int deepth,num=0 ;
	Create_BiTree(&T);//一般涉及到變化的都會取地址 
	printf("先序遍歷二叉樹:\n");
	TraverseBiTree(T);
	printf("\n");
	printf("中序遍歷二叉樹:\n");
	InOrderBiTree(T);
	printf("\n");
	printf("后序遍歷二叉樹:\n");
	PostOrderBiTree(T);
	printf("\n層次遍歷結果:");
    LevelOrder_BiTree(T);
	printf("\n");
	deepth=TreeDeep(T);
	printf("樹的深度為:%d",deepth);
	printf("\n");
	printf("樹的葉子結點為:");
	Leafcount(T,num);
	printf("\n樹的葉子結點個數為:%d",num);
	return 0;
}

運行演示

線索二叉樹的中序遍歷

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

typedef struct BiThrNode
{
    char data;
	struct BiThrNode *lchild,*rchild;      /*左右孩子指針*/
	int LTag,RTag;             			    /*左右標志*/
}BiThrNode,*BiThrTree;

BiThrTree pre;



void CreateBiTree(BiThrTree *T){
    char ch;
    ch = getchar();
    //當輸入的是"#"時,認為該子樹為空
    if(ch == '#')
        *T = NULL;
    //創建樹結點
    else{
        *T = (BiThrTree)malloc(sizeof(struct BiThrNode));
        (*T)->data = ch; //生成樹結點
        //生成左子樹
        CreateBiTree(&(*T)->lchild);
        //生成右子樹
        CreateBiTree(&(*T)->rchild);
    }
}

/*以結點p為根的子樹中序線索化*/
void InThreading(BiThrTree p)
{
	/*pre是全局變量,初始化時其右孩子指針為空,便於在樹的最左點開始建線索*/
	if(p)
	{
		InThreading(p->lchild);            /*左子樹遞歸線索化*/
		if(!(p->lchild) )                      /*p的左孩子為空*/
		{                  
			p->LTag=1;                     /*給p加上左線索*/
			p->lchild=pre;                 /*p的左孩子指針指向pre(前驅)*/
		}
		else
		{
			p->LTag=0;
		}
		if(!(pre->rchild) )                  /*pre的右孩子為空*/
		{
			pre->RTag=1;                  /*給pre加上右線索*/
			pre->rchild=p;                /*pre的右孩子指針指向p(后繼)*/
		}
		else
		{
			pre->RTag=0;
		}
		pre=p;                            /*保持pre指向p的前驅*/
		InThreading(p->rchild);           /*右子樹遞歸線索化*/
	}
}
/*帶頭結點的中序線索化*/
void InOrderThreading(BiThrTree &Thrt,BiThrTree T)
{
	/*中序遍歷二叉樹T,並將其中序線索化,Thrt指向頭結點*/
	Thrt=new BiThrNode;  		/*建頭結頭*/
	Thrt->LTag=0;               /*頭結點有左孩子,若樹非空,則其左孩子為樹根*/       
	Thrt->RTag=1;               /*頭結點的右孩子指針為右線索*/
	Thrt->rchild=Thrt;          /*初始化時右指針指向自己*/
	if(!T) Thrt->lchild=Thrt;   /*若樹為空,則左指針也指向自己*/
	else
	{
		Thrt->lchild=T; pre=Thrt; /*頭結點的左孩子指向根,pre初值指向頭結點*/
		InThreading(T);          /*調用上述算法,對以T為根的二叉樹進行中序線索化*/
		pre->rchild=Thrt;        /*算法結束后,pre為最右結點,pre的右線索指向頭結點*/
		pre->RTag=1;
		Thrt->rchild=pre;        /*頭結點的右線索指向pre*/
	} 
}  
/*遍歷中序線索二叉樹*/
void InOrderTraverse_Thr(BiThrTree T)
{
	/*T指向頭結點,頭結點的左鏈lchild指向根結點*/
	/*中序遍歷二叉線索樹T的非遞歸算法,對每個數據元素直接輸出*/
	BiThrTree p=T->lchild;    /*p指向根結點*/        
	while(p!=T)
	{
        while(p->LTag == 0)      /*沿左孩子向下*/
		{
		     p=p->lchild;
		}
		cout<<p->data<<" ";           /*訪問其左子樹為空的結點*/
		while(p->RTag == 1 && p->rchild!=T)  /*沿右線索訪問后繼結點*/
		{
		    p=p->rchild;
			cout<<p->data<<" ";
		}
		p=p->rchild;
	}
	cout<<p->data;
}
int main()
{
	BiThrTree T;
	BiThrTree Thrt;
	cout<<"Input the Threaded BinaryTree 's node:"<<endl;
	CreateBiTree(&T);
	InOrderThreading(Thrt,T); /*帶頭結點的中序線索化*/
	cout<<"InOrderTraverse_Thr:"<<endl;
	InOrderTraverse_Thr(T);   /*遍歷中序線索二叉樹*/
	return 0;
}

運行演示

二叉樹結構圖

參考文獻

  • 數據結構-用C語言描述(第二版)[耿國華]


免責聲明!

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



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