您的位置:首页 > 理论基础 > 数据结构算法

(六)数据结构之二叉树的简单实现

2017-09-17 18:45 441 查看

1、基本数据结构

/* 二叉树的基本数据结构的定义 */
typedef char ElementType;
typedef struct TreeNode *BinTree;
typedef BinTree Position;
struct TreeNode{
ElementType Data;
BinTree Left;
BinTree Right;
};
采用链式存储方式来存储二叉树,每个二叉树结点包括一个数据域和两个指针域,其中数据域用来存放二叉树对应结点的数据,指针域分别用来指向其左右孩子结点。

2、二叉树的递归遍历

2.1 先序遍历

/* 先序递归遍历 */
void PreOrderTraversal( BinTree BT )
{
if( BT )
{
printf("%c ", BT->Data);
PreOrderTraversal( BT->Left );
PreOrderTraversal( BT->Right );
}
}

2.2 中序遍历

/* 中序递归遍历 */
void InOrderTraversal( BinTree BT )
{
if( BT )
{
InOrderTraversal( BT->Left );
printf("%c ", BT->Data);
InOrderTraversal( BT->Right );
}
}

2.3 后序遍历

/* 后序递归遍历 */
void PostOrderTraversal( BinTree BT )
{
if( BT )
{
PostOrderTraversal( BT->Left );
PostOrderTraversal( BT->Right);
printf("%c ", BT->Data);
}
}

3、二叉树的非递归遍历

考虑到算法的复杂度问题常常为了提高效率而采用非递归的二叉树遍历方法,为了实现非递归遍历需要借助一种基本的数据结构堆栈,堆栈的具体实现可以参考这篇文章http://blog.csdn.net/tech_pro/article/details/78011998

3.1 先序遍历

/* 先序非递归遍历 */
void PreOrderTraversalWithStack( BinTree BT )
{
BinTree T = BT;
Stack *S = CreateStack(); 	/*创建并初始化堆栈S*/
while( T || !IsEmpty(S) )
{
while(T)
{
/*一直向左并将沿途结点压入堆栈*/
printf("%c ", T->Data); 	/*(访问)打印结点*/
Push(S,T);
T = T->Left;
}
if(!IsEmpty(S))
{
T = Pop(S); 				/*结点弹出堆栈*/
T = T->Right; 				/*转向右子树*/
}
}
DestroyStack(S);
}

3.2 中序遍历

/* 中序非递归遍历 */
void InOrderTraversalWithStack( BinTree BT )
{
BinTree T = BT;
Stack *S = CreateStack(); 	/*创建并初始化堆栈S*/
while( T || !IsEmpty(S) )
{
while(T)
{
/*一直向左并将沿途结点压入堆栈*/
Push(S,T);
T = T->Left;
}
if(!IsEmpty(S))
{
T = Pop(S); 				/*结点弹出堆栈*/
printf("%c ", T->Data); 	/*(访问)打印结点*/
T = T->Right; 				/*转向右子树*/
}
}
DestroyStack(S);
}

3.3 后序遍历

/* 后序非递归遍历 */
void PostOrderTraversalWithStack( BinTree BT )
{
BinTree T = BT;
BinTree Done = NULL;		/* 做一个标记来判断相关结点是否已经被访问 */
Stack *S = CreateStack(); 	/*创建并初始化堆栈S*/
while( T || !IsEmpty(S) )
{
while(T)
{
/*一直向左并将沿途结点压入堆栈*/
Push(S,T);
T = T->Left;
}
if(!IsEmpty(S))
{
T = Pop(S); 				/*结点弹出堆栈*/;
if((T->Right == NULL) || (T->Right == Done))
{
printf("%c ", T->Data); 	/*(访问)打印结点*/
Done = T;
T = NULL;
}
else
{
Push(S, T);
T = T->Right;
}
}
}
DestroyStack(S);
}

4、二叉树的层次遍历

二叉树的层次遍历要借助一种基本的数据结构队列,关于队列的具体实现可以参考这篇文章:http://blog.csdn.net/tech_pro/article/details/78012076

/* 层次遍历二叉树 */
void LevelOrderTraversal ( BinTree BT )
{
Queue *Q = NULL;
BinTree T = NULL;
if ( !BT ) return; /* 若是空树则直接返回 */
Q = CreatQueue(); /*创建并初始化队列Q*/
AddQ( Q, BT );
while ( !IsEmptyQ( Q ) )
{
T = DeleteQ( Q );
printf("%c ", T->Data); /*访问取出队列的结点*/
if ( T->Left ) AddQ( Q, T->Left );
if ( T->Right ) AddQ( Q, T->Right );
}
}

5、基本的应用

5.1 输出叶子结点

/* 输出二叉树的叶子结点, 按照先序遍历 */
int PreOrderPrintLeaves( BinTree BT )
{
int i = 0;
if( BT )
{
if ( !BT->Left && !BT->Right )
{
printf("%c ", BT->Data );
i = i + 1;
}
PreOrderPrintLeaves ( BT->Left );
PreOrderPrintLeaves ( BT->Right );
}
return i;
}

5.2 求二叉树的高度

/* 求二叉树的高度 */
int PostOrderGetHeight( BinTree BT )
{
int HL, HR, MaxH;
if( BT )
{
HL = PostOrderGetHeight(BT->Left); 		/*求左子树的深度*/
HR = PostOrderGetHeight(BT->Right); 	/*求右子树的深度*/
MaxH = (HL > HR) ? HL : HR; 			/*取左右子树较大的深度*/
return ( MaxH + 1 ); 					/*返回树的深度*/
}
else return 0; 	/* 空树深度为0 */
}

6、实例代码完整实现

/* 实现二叉树的一些基本操作 */
#include <stdio.h>
#include <stdlib.h>

/* 二叉树的基本数据结构的定义 */
typedef char ElementType;
typedef struct TreeNode *BinTree;
typedef BinTree Position;
struct TreeNode{
ElementType Data;
BinTree Left;
BinTree Right;
};

/* 创建一颗二叉树, 先创建根节点,然后创建左子树,最后创建右子树*/
BinTree CreatBinTree()
{
ElementType data;
BinTree T;
scanf("%c ", &data); // 通过控制台获得一个结点数据
if('#' == data) // 如果为空树结点
{
T = NULL;
}
else // 如果为非空树结点
{
T = (BinTree)malloc(sizeof(struct TreeNode)); // 分配一块内存给根结点
if(NULL == T) return NULL;
T->Data= data;
T->Left = CreatBinTree(); // 递归创建左子树
T->Right = CreatBinTree(); // 递归创建右子树
}
return T; // 返回树根结点
}

/* 销毁一颗二叉树 */
void DestroyBinTree(BinTree BT)
{
if (BT)
{
DestroyBinTree(BT->Left);
DestroyBinTree(BT->Right);
free(BT);
BT = NULL;
}
}

/***************************************** 递归遍历 *******************************************/

/* 先序递归遍历 */
void PreOrderTraversal( BinTree BT )
{
if( BT )
{
printf("%c ", BT->Data);
PreOrderTraversal( BT->Left );
PreOrderTraversal( BT->Right );
}
}

/* 中序递归遍历 */
void InOrderTraversal( BinTree BT )
{
if( BT )
{
InOrderTraversal( BT->Left );
printf("%c ", BT->Data);
InOrderTraversal( BT->Right );
}
}

/* 后序递归遍历 */ void PostOrderTraversal( BinTree BT ) { if( BT ) { PostOrderTraversal( BT->Left ); PostOrderTraversal( BT->Right); printf("%c ", BT->Data); } }

/**********************定义堆栈的基本操作和数据结构***************************/

/* 定义堆栈的数据结构 */
#define MaxSize 20
typedef BinTree ElementTypeB;
typedef struct _Stack{
ElementTypeB Data[MaxSize];
int Top;
} Stack;

/* 创建一个堆栈 */
Stack *CreateStack()
{
Stack *S = (Stack*)malloc(sizeof(Stack));
if(NULL != S) S->Top = -1;
return S;
}

/* 销毁一个堆栈 */
void DestroyStack(Stack *PtrS)
{
if(NULL != PtrS)
{
free(PtrS);
PtrS = NULL;
}
}

/* 判断一个堆栈是否为空,为空返回1,否者返回0 */
int IsEmpty( Stack *S )
{
return (S->Top == -1);
}

/* 判断一个堆栈是否为满, 为满返回1,否者返回0 */
int IsFull( Stack *S )
{
return (S->Top == MaxSize - 1);
}

/* 压栈操作,先移动Top,后压入 */
void Push( Stack *PtrS, ElementTypeB item )
{
if (IsFull(PtrS)) // 判断是否栈满
{
printf("Stack is full!\n");
return;
}
else
{
PtrS->Data[++(PtrS->Top)] = item;
return;
}
}

/* 出栈操作,先弹出,后移动Top */
ElementTypeB Pop( Stack *PtrS )
{
if (IsEmpty(PtrS)) // 判断堆栈是否为空
{
printf("The stack is empty!\n");
return NULL;
}
else
return ( PtrS->Data[(PtrS->Top)--] );
}

/*********************************结束***************************************/

/***************************************** 非递归遍历 *******************************************/

/* 先序非递归遍历 */ void PreOrderTraversalWithStack( BinTree BT ) { BinTree T = BT; Stack *S = CreateStack(); /*创建并初始化堆栈S*/ while( T || !IsEmpty(S) ) { while(T) { /*一直向左并将沿途结点压入堆栈*/ printf("%c ", T->Data); /*(访问)打印结点*/ Push(S,T); T = T->Left; } if(!IsEmpty(S)) { T = Pop(S); /*结点弹出堆栈*/ T = T->Right; /*转向右子树*/ } } DestroyStack(S); }
/* 中序非递归遍历 */
void InOrderTraversalWithStack( BinTree BT )
{
BinTree T = BT;
Stack *S = CreateStack(); /*创建并初始化堆栈S*/
while( T || !IsEmpty(S) )
{
while(T)
{
/*一直向左并将沿途结点压入堆栈*/
Push(S,T);
T = T->L
c623
eft;
}
if(!IsEmpty(S))
{
T = Pop(S); /*结点弹出堆栈*/
printf("%c ", T->Data); /*(访问)打印结点*/
T = T->Right; /*转向右子树*/
}
}
DestroyStack(S);
}

/* 后序非递归遍历 */ void PostOrderTraversalWithStack( BinTree BT ) { BinTree T = BT; BinTree Done = NULL; /* 做一个标记来判断相关结点是否已经被访问 */ Stack *S = CreateStack(); /*创建并初始化堆栈S*/ while( T || !IsEmpty(S) ) { while(T) { /*一直向左并将沿途结点压入堆栈*/ Push(S,T); T = T->Left; } if(!IsEmpty(S)) { T = Pop(S); /*结点弹出堆栈*/; if((T->Right == NULL) || (T->Right == Done)) { printf("%c ", T->Data); /*(访问)打印结点*/ Done = T; T = NULL; } else { Push(S, T); T = T->Right; } } } DestroyStack(S); }

/**************************定义队列操作的基本数据和算法*************************** */

/* 定义队列的基本数据结果 */
//#define MaxSize 20
typedef BinTree ElementTypeC;
typedef struct _Queue{
ElementTypeC Data[ MaxSize ];
int rear;
int front;
} Queue;

/* 创建一个空队列 */
Queue *CreatQueue()
{
Queue *Q = (Queue*)malloc(sizeof(Queue));
if(NULL != Q)
{
Q->front = 0;
Q->rear = 0;
}
return Q;
}

/* 消除一个队列 */
void DestroyQueue(Queue *PtrQ)
{
if(NULL != PtrQ)
free(PtrQ);
PtrQ = NULL;
}

/* 判断队列是否为空,1为空,0非空 */
int IsEmptyQ( Queue *PtrQ )
{
return (PtrQ->front == PtrQ->rear);
}

/* 判断队列是否为满,1为满,0为空 */
int IsFullQ( Queue *PtrQ )
{
return ((PtrQ->rear+1)%MaxSize == PtrQ->front);
}

/* 向循环队列尾部插入一个元素 */
void AddQ( Queue *PtrQ, ElementTypeC item)
{
if ( IsFullQ(PtrQ) )
{
printf("The queue is full!\n");
return;
}
PtrQ->rear = (PtrQ->rear+1)% MaxSize;
PtrQ->Data[PtrQ->rear] = item;
}

/* 删除循环队列的队头的元素 */
ElementTypeC DeleteQ ( Queue *PtrQ )
{
if ( IsEmptyQ(PtrQ) )
{
printf("The queue is empty!\n");
return NULL;
}
else
{
PtrQ->front = (PtrQ->front+1)% MaxSize;
return PtrQ->Data[PtrQ->front];
}
}

/********************************************队列定义结束****************************************/

/* 层次遍历二叉树 */
void LevelOrderTraversal ( BinTree BT )
{
Queue *Q = NULL;
BinTree T = NULL;
if ( !BT ) return; /* 若是空树则直接返回 */
Q = CreatQueue(); /*创建并初始化队列Q*/
AddQ( Q, BT );
while ( !IsEmptyQ( Q ) )
{
T = DeleteQ( Q );
printf("%c ", T->Data); /*访问取出队列的结点*/
if ( T->Left ) AddQ( Q, T->Left );
if ( T->Right ) AddQ( Q, T->Right );
}
}

/********************************************定义二叉树的一些其他应用****************************************/

/* 输出二叉树的叶子结点, 按照先序遍历 */
int PreOrderPrintLeaves( BinTree BT )
{
int i = 0;
if( BT )
{
if ( !BT->Left && !BT->Right )
{
printf("%c ", BT->Data );
i = i + 1;
}
PreOrderPrintLeaves ( BT->Left );
PreOrderPrintLeaves ( BT->Right );
}
return i;
}

/* 求二叉树的高度 */ int PostOrderGetHeight( BinTree BT ) { int HL, HR, MaxH; if( BT ) { HL = PostOrderGetHeight(BT->Left); /*求左子树的深度*/ HR = PostOrderGetHeight(BT->Right); /*求右子树的深度*/ MaxH = (HL > HR) ? HL : HR; /*取左右子树较大的深度*/ return ( MaxH + 1 ); /*返回树的深度*/ } else return 0; /* 空树深度为0 */ }

/* 程序入口 */
int main()
{
BinTree tree = NULL;

/* 创建一颗二叉树 */
tree = CreatBinTree();

/* 递归遍历 */
printf("************************Traversal***************************\n");
printf("Pre : "); PreOrderTraversal(tree); printf("\n");
printf("In : "); InOrderTraversal(tree); printf("\n");
printf("Post : "); PostOrderTraversal(tree); printf("\n");

/* 非递归遍历 */
printf("************************normal******************************\n");
printf("Pre : "); PreOrderTraversalWithStack(tree); printf("\n");
printf("In : "); InOrderTraversalWithStack(tree); printf("\n");
printf("Post : "); PostOrderTraversalWithStack(tree); printf("\n");

/* 层次遍历二叉树 */
printf("************************level*******************************\n");
printf("Level : "); LevelOrderTraversal(tree); printf("\n");

/* 二叉树的一些基本使用 */
printf("************************apply*******************************\n");
printf("Leaves : "); PreOrderPrintLeaves(tree); printf("\n");
printf("The height of this tree is %d\n", PostOrderGetHeight(tree));

DestroyBinTree(tree); /* 销毁一棵树 */
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息