1. 程式人生 > >二叉樹的定義及基本操作

二叉樹的定義及基本操作

(1)定義二叉樹的鏈式儲存結構;

(2)建立一顆二叉連結串列表示的二叉樹;

(3)對其進行前序,中序(非遞迴),後序輸出。

(4)統計二叉樹中葉子結點個數和度為2的結點個數。

         建立的二叉樹為:

                   

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define OK 1
#define ERROR 0
#define OVERFLOW 0
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
typedef char TElemType;
typedef int Status;
//定義二叉連結串列的結點結構
typedef struct BiTNode { // 結點結構                            
 TElemType data;
 struct BiTNode  *lchild, *rchild; //左右孩子指標
} BiTNode, *BiTree;
typedef BiTree SElemType;
typedef struct{
 SElemType *base;  //棧底指標
 SElemType *top;   //棧頂指標
 int stacksize;    //棧的容量
}SqStack; //定義一個順序棧

Status InitStack(SqStack &S){
 S.base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
 if (!S.base){
  printf("棧溢位!\n");
  exit(OVERFLOW);
 }
 S.top = S.base;
 S.stacksize = STACK_INIT_SIZE;
 return OK;
}//初始化一個順序棧

Status StackEmpty(SqStack S){
 if (S.top == S.base){
  return OK;
 }
 return ERROR;
}//判斷一個棧是否為空

//往棧裡面插入元素e
Status Push(SqStack &S, BiTree p){
 if (S.top - S.base >= S.stacksize){
  S.base = (SElemType *)realloc(S.base, (S.stacksize + STACKINCREMENT) * sizeof(SElemType));
  if (!S.base){
   printf("棧溢位!\n");
   return OVERFLOW;
  }
  S.top = S.base + S.stacksize;
  S.stacksize += STACKINCREMENT;
 }//若棧滿,追加儲存空間
 *S.top++ = p;
 return OK;
}

//刪除棧頂元素,用指標p返回棧裡存放的根指標
Status Pop(SqStack &S, BiTree &p){
 if (StackEmpty(S))
  return ERROR; //判空
 p = *(--S.top);
 return OK;
}
Status CreateBiTree(BiTree &T)
{//按先序次序輸入二叉樹中結點的值,空格字元表示空樹,構造二叉連結串列表示的二叉樹T。
char ch;
scanf("%c",&ch);
if(ch==' ')T=NULL;
else{
	if(!(T=(BiTNode *)malloc(sizeof(BiTNode))))
		exit(OVERFLOW);
	T->data=ch;      //生成根結點
	CreateBiTree(T->lchild);//構造左子樹
	CreateBiTree(T->rchild);//構造右子樹
}
return OK;
}

Status PrintElement(TElemType e)
	{
		printf("%c",e)//輸出元素e的值;
		return OK;
	}
Status PreOrderTraverse(BiTree T,Status(* Visit)(TElemType e))
{//採用二叉連結串列儲存結構,Visit是對資料元素操作的應用函式
	//先序遍歷二叉樹T的遞迴演算法,對每個資料元素呼叫Visit函式
	if(T){
		if(Visit(T->data))
			if(PreOrderTraverse(T->lchild,Visit))
				if(PreOrderTraverse(T->rchild,Visit)) return OK;
				return ERROR;
				}
	else return OK;
}
Status InOrderTraverse(BiTree T,Status(*Visit)(TElemType e))
{//中序遍歷二叉樹T的非遞迴演算法,對每個資料元素呼叫函式Visit
	SqStack S;
	InitStack(S);
	BiTree p=T;
	while(p||!StackEmpty(S))
	{
		if(p)
		{
			Push(S,p);
			p=p->lchild;//根指標進棧,遍歷左子樹
		}else
		{//根指標退棧,訪問根結點,遍歷右子樹
			Pop(S,p);
			if(!Visit(p->data))
				return ERROR;
			p=p->rchild;
		}
	}
	return OK;
}
Status PostOrderTraverse(BiTree T,Status(*Visit)(TElemType e))
{//後序遍歷二叉樹T的遞迴演算法,對每個資料元素呼叫Visit函式

	if(T){
			if(PreOrderTraverse(T->lchild,Visit))
				if(PreOrderTraverse(T->rchild,Visit))
					if(Visit(T->data))return OK;
				return ERROR;
				}
	else return OK;
}
void CountLeaf(BiTree T,int& count)
{//計算葉子結點數
	if(T)
	{
		if((!T->lchild)&&(!T->rchild))
			count++;
		CountLeaf(T->lchild,count);
		CountLeaf(T->rchild,count);
	}
}
void Count(BiTree T,int& n2)
{//計算度為2的結點數
	if(T)
	{
		if((T->lchild)&&(T->rchild))
			n2++;
		Count(T->lchild,n2);
		Count(T->rchild,n2);
	}
}
int main()
{
	int n0=0,n2=0;
	BiTree T;
	printf("按先序次序輸入一個二叉樹的結點值:\n");
	if(CreateBiTree(T))
	{
		printf("建立二叉樹成功\n");
	}
	else
		printf("建立二叉樹失敗\n");
	printf("先序遍歷結果為:\n");
	if(PreOrderTraverse(T,PrintElement))
	{
		printf("\n");
	}
	else
		printf("遍歷失敗\n");
	printf("中序遍歷結果為:\n");
	if(InOrderTraverse(T,PrintElement))
	{
		printf("\n");
	}
	else
		printf("遍歷失敗\n");
		printf("後序遍歷結果為:\n");
	if(PostOrderTraverse(T,PrintElement))
	{
		printf("\n");
	}
	else
		printf("遍歷失敗\n");
	CountLeaf(T,n0);
		printf("葉子的結點數位:%d\n",n0);
	Count(T,n2);
	printf("度為2的結點個數為:%d\n",n2);
	return 0;
}