1. 程式人生 > >用C語言實現二叉樹的結構和常用操作

用C語言實現二叉樹的結構和常用操作

#include<stdio.h>
#include <stdlib.h>
typedef float ElemType;
typedef struct S_BiTNode//定義結點型別結構體
{
	ElemType data;//資料域
	struct S_BiTNode * lchild;//左子樹
	struct S_BiTNode * rchild;//右子樹
	struct S_BiTNode * parent;//父結點
}BiTNode;
/***********************函式定義函式定義定*****************************/
//
/**統計總結點數**/
int NodeCount(BiTNode *root)
{
	int Count=0,LCount=0,RCount=0;
	if(root==NULL)
		return 0;
	/*遞迴方法統計*/
	LCount=NodeCount(root->lchild);//左子樹結點數
	RCount=NodeCount(root->rchild);//右子樹結點數

	Count=LCount+RCount+1;//左子樹+右子樹+根結點
	return Count;
}

//
/**向二叉樹中插入結點**/
void InsertIntoBitTree(BiTNode **root,ElemType data)
{
	/*建立新結點儲存待插入的data*/
	BiTNode *newNode=(BiTNode*)malloc(sizeof(BiTNode));
	newNode->data=data;
	newNode->lchild=NULL;
	newNode->rchild=NULL;
	//考慮到 當輸入是空樹時 需要改變根結點(BiTNode *root)的值,所以這裡要求輸入根節點的地址(BiTNode **root型別)
	if(*root==NULL)//說明是空樹
		{
			*root=newNode;//將新結點的指標newNode賦值給根結點的指標
			(*root)->parent=NULL;
			(*root)->lchild=NULL;
			(*root)->rchild=NULL;
		}
	else if((*root)->lchild==NULL)
	{
		/*左子樹為空 則將新結點newNode的指標賦值給左子樹結點的指標*/
		(*root)->lchild=newNode;
		(*root)->lchild->parent=*root;//左子樹的父節點為根結點
		
	}
		
	else if((*root)->rchild==NULL)
	{
		/*右子樹為空 則將新結點newNode的指標賦值給右子樹結點的指標*/
		(*root)->rchild=newNode;
		(*root)->rchild->parent=*root;//右子樹的父節點為根結點
	}
	
	/*如果根節點、左右子樹都不為空 遞歸向左子樹插入data*/	
	/*這樣構造的樹的特點是:根結點的右子樹只有一個結點*/
	else
		InsertIntoBitTree(&((*root)->lchild),data);
	
}
//
/*向二叉樹中有序插入資料滿足:根結點的資料域大於左結點並且小於右結點*/
void OrderInsert(BiTNode **root,ElemType data)
{
	/*建立新結點儲存待插入的data*/
	BiTNode *newNode=(BiTNode*)malloc(sizeof(BiTNode));
	newNode->data=data;
	newNode->lchild=NULL;
	newNode->rchild=NULL;
	//考慮到 當輸入是空樹時 需要改變根結點(BiTNode *root)的值,所以這裡要求輸入根節點的地址(BiTNode **root型別)
	if(*root==NULL)//說明是空樹
		{
			*root=newNode;//將新結點的指標newNode賦值給根結點的指標
			(*root)->parent=NULL;
			(*root)->lchild=NULL;
			(*root)->rchild=NULL;
		}
		
    	else//不是空樹
	{
		BiTNode *node=(BiTNode*)malloc(sizeof(BiTNode));
		BiTNode *parent=(BiTNode*)malloc(sizeof(BiTNode));
		//BiTNode *node,*parent;
		node=(*root);
		parent=(*root);
		while(node!=NULL)
		{
			parent=node;
			if(node->data==data)
			{printf("data to insert aleady exist");exit(-1);}
			if(node->data>data)
				node=node->lchild;
			else
				node=node->rchild;
		}
		
		if(data>parent->data)
			parent->rchild=newNode;
		else
			parent->lchild=newNode;
			
	}
		
}



//
/*先序遍歷並輸出:根結點 左 右*/
void PrePrint(BiTNode *root)
{
	if(root==NULL)
	{
		printf("invalid PrePrint");
		exit(-1);
	}
	printf("%f\t",root->data);
	if(root->lchild!=NULL)
	PrePrint(root->lchild);
	if(root->rchild!=NULL)
	PrePrint(root->rchild);
	  
}

//
/*中序遍歷並輸出:左 根結點 右*/
void MidPrint(BiTNode *root)
{
	if(root==NULL)
	{
		printf("invalid MidPrint");
		exit(-1);
	}
	if(root->lchild!=NULL)
	MidPrint(root->lchild);
	printf("%f\t",root->data);
	if(root->rchild!=NULL)
	MidPrint(root->rchild);
	
}

//
/*後續遍歷並輸出:左 右 跟結點*/
void PostPrint(BiTNode *root)
{
	if(root==NULL)
	{
		printf("invalid MidPrint");
		exit(-1);
	}
	if(root->lchild!=NULL)
	PostPrint(root->lchild);
	if(root->rchild!=NULL)
	PostPrint(root->rchild);
	printf("%f\t",root->data);
	
}

//
/*統計葉子結點數*/
int LeafNodeNum(BiTNode *root)
{
	int num=0;
	if((root->lchild==NULL)&&(root->rchild==NULL))//說明該結點是葉子結點
		++num;
	else if((root->lchild!=NULL)&&((root->rchild!=NULL)))//分別對左、右子樹遞迴操作
		{
			num=num+LeafNodeNum(root->lchild);
			num=num+LeafNodeNum(root->rchild);
		}
	else if (root->lchild!=NULL)//左子樹遞迴操作
		num=num+LeafNodeNum(root->lchild);
	else 
		num=num+LeafNodeNum(root->rchild);//右子樹遞迴操作
	
	return num;
}

//
/*從左到右輸出葉子結點 返回葉子結點個數*/
int LeafNodePrint(BiTNode *root)
{
	int  num=0;
	BiTNode *p=root;
	if((p->lchild==NULL)&&(p->rchild==NULL))//說明該結點是葉子結點
	{
		printf("%f\t",p->data);
		++num;
	}
	else if((p->lchild!=NULL)&&((p->rchild!=NULL)))//分別對左、右子樹遞迴操作
	{
		num+=LeafNodePrint(root->rchild);
		num+=LeafNodePrint(root->lchild);
	
	}
	else if( (p->lchild!=NULL))
		num+=LeafNodePrint(root->lchild);//左子樹遞迴操作
	else
		num+=LeafNodePrint(root->rchild);//右子樹遞迴操作
	return num;
}

//
/*統計高度*/
int Height(BiTNode *root)
{
	int lh=1,rh=1;
	if(root==NULL)
		return 0;
	lh+=Height(root->lchild);
	rh+=Height(root->rchild);
	return lh>=rh?lh:rh;
	
	
}

//
/*銷燬樹*/
void destory(BiTNode *root)
{
	if((root->lchild==NULL)&&(root->rchild==NULL))//free葉子結點
		free(root);
	else if((root->lchild!=NULL)&&((root->rchild!=NULL)))//分別對左、右子樹遞迴操作
	{
		destory(root->lchild);
		destory(root->rchild);
		free(root);//銷燬根結點
	}
	else if(root->lchild!=NULL)//左子樹遞迴操作
		{
			destory(root->lchild);
			free(root);//銷燬根結點
		}
	else						//右子樹遞迴操作
		{
			destory(root->rchild);
			free(root);//銷燬根結點
		}

}

/*******************************************下面是主函式***********************************************/
void main()
{
		BiTNode *MyTree=NULL;//定義根結點 初始化為空
		/***向二叉樹中插入子節點***/
		InsertIntoBitTree(&MyTree,1);
		InsertIntoBitTree(&MyTree,2);
		InsertIntoBitTree(&MyTree,3);
		InsertIntoBitTree(&MyTree,4);
		InsertIntoBitTree(&MyTree,5);
		printf("node numbers: %d\n",NodeCount(MyTree));//輸出已構造二叉樹的結點數
		printf("height:%d\n",Height(MyTree));//輸出已構造二叉樹的高度
		printf("PreOder Ouput:\n");
		PrePrint(MyTree);//按前序訪問順序 輸出樹的結點
		printf("MidOder Ouput:\n");
		MidPrint(MyTree);//按中序訪問順序 輸出樹的結點
		printf("PostOder Ouput:\n");
		PostPrint(MyTree);//按後序訪問順序 輸出樹的結點
		printf("Leaf Node %d:\n",LeafNodeNum(MyTree));
		LeafNodePrint(MyTree);
		destory(MyTree);//釋放樹的記憶體 銷燬樹
		
		
	  
		
}