包含了四种遍历方法的 BST
tree.h
typedef int ElementType;
/* START: fig4_16.txt */
#ifndef _Tree_H
#define _Tree_H
struct TreeNode; // 定义结构体节点
typedef struct TreeNode *Position; // 指向节点的指针
typedef struct TreeNode *SearchTree; // 指针,表示搜索树,是搜索树的根节点
SearchTree MakeEmpty( SearchTree T );
Position Find( ElementType X, SearchTree T );
Position FindMin( SearchTree T );
Position FindMax( SearchTree T );
SearchTree Insert( ElementType X, SearchTree T );
SearchTree Delete( ElementType X, SearchTree T );
ElementType Retrieve( Position P );
/* 后增的树的遍历方法 */
void PreOrderTraversal(SearchTree T);
void InOrderTraversal(SearchTree T);
void PostOrderTraversal(SearchTree T);
void LevelOrderTraversal(SearchTree T);
/* 后增的树的遍历方法 */
#endif /* _Tree_H */
/* END */
tree.c
#include "tree.h"
#include <stdlib.h>
#include "fatal.h"
#include "queueli.h"
struct TreeNode
{
ElementType Element; // 树节点存储的元素
SearchTree Left; // 左子树
SearchTree Right; // 右子树
};
/* START: fig4_17.txt */
// 建立一棵空树
SearchTree
MakeEmpty(SearchTree T)
{
if (T != NULL)
{
MakeEmpty(T->Left); // 递归删除左子树
MakeEmpty(T->Right); // 递归删除右子树
free(T); // 释放该节点
}
return NULL;
}
/* END */
/* START: fig4_18.txt */
// 二叉搜索树的查找操作
Position
Find(ElementType X, SearchTree T)
{
if (T == NULL)
return NULL;
if (X < T->Element) // 如果待查找元素比根节点小,那么递归查找左子树
return Find(X, T->Left);
else if (X > T->Element) // 如果待查找元素比根节点大,那么递归查找右子树
return Find(X, T->Right);
else
return T;
}
/* END */
/* START: fig4_19.txt */
// 查找最小元素,即找出最左边的叶子节点
Position
FindMin(SearchTree T)
{
if (T == NULL)
return NULL;
else if (T->Left == NULL)
return T;
else
return FindMin(T->Left);
}
/* END */
/* START: fig4_20.txt */
// 查找最大值
Position
FindMax(SearchTree T)
{
if (T != NULL)
while (T->Right != NULL)
T = T->Right;
return T;
}
/* END */
/* START: fig4_22.txt */
// 插入操作
SearchTree
Insert(ElementType X, SearchTree T)
{
/* 1*/ if (T == NULL)
{
/* Create and return a one-node tree 创建并返回一个单节点树 */
/* 2*/ T = malloc(sizeof(struct TreeNode));
/* 3*/ if (T == NULL)
/* 4*/ FatalError("Out of space!!!"); // 空间用尽的情况
else
{
/* 5*/ T->Element = X; // 赋值
/* 6*/ T->Left = T->Right = NULL; // 左右子树置空
}
} else
/* 7*/ if (X < T->Element)
/* 8*/ T->Left = Insert(X, T->Left); // 递归寻找合适的插入位置
else
/* 9*/ if (X > T->Element)
/*10*/ T->Right = Insert(X, T->Right);
/* Else X is in the tree already; we'll do nothing */
/*11*/ return T; /* Do not forget this line!! */
}
/* END */
/* START: fig4_25.txt */
// 删除操作
SearchTree
Delete(ElementType X, SearchTree T)
{
Position TmpCell;
// 寻找节点
if (T == NULL)
Error("Element not found");
else if (X < T->Element) /* Go left */
T->Left = Delete(X, T->Left);
else if (X > T->Element) /* Go right */
T->Right = Delete(X, T->Right);
else /* Found element to be deleted 找到了该删除的节点 */
{
if (T->Left && T->Right) /* Two children 有两个孩子 */
{
/* Replace with smallest in right subtree 用右子树中最小的节点进行替换 */
TmpCell = FindMin(T->Right); // 找出右子树中最小的节点
T->Element = TmpCell->Element; // 替换
T->Right = Delete(T->Element, T->Right); // 删除刚刚的那个在右子树中最小的节点
} else /* One or zero children 有 1 个或者 0 个孩子 */
{
TmpCell = T;
if (T->Left == NULL) /* Also handles 0 children */
T = T->Right; // 如果左子树为空,那么将 T 更新为右子树,下同
else if (T->Right == NULL)
T = T->Left;
free(TmpCell); // 释放原来的 T 节点
}
}
return T;
}
/* END */
// 取出 Position P 中的元素
ElementType
Retrieve(Position P)
{
return P->Element;
}
/* 后增方法 */
// 先序
void PreOrderTraversal(SearchTree T)
{
if (T) {
printf("%d ", T->Element);
PreOrderTraversal(T->Left);
PreOrderTraversal(T->Right);
}
}
// 中序
void InOrderTraversal(SearchTree T) {
if (T) {
InOrderTraversal(T->Left);
printf("%d ", T->Element);
InOrderTraversal(T->Right);
}
}
// 后序
void PostOrderTraversal(SearchTree T) {
if (T) {
PostOrderTraversal(T->Left);
PostOrderTraversal(T->Right);
printf("%d ", T->Element);
}
}
// 层序
void LevelOrderTraversal(SearchTree T) {
Queue Q;
SearchTree ST;
if (!T) return; /* 如果是空树就直接返回 */
Q = CreateQueue();
Enqueue(T, Q); /* 将根节点入队 */
while (!IsEmpty(Q)) {
ST = FrontAndDequeue(Q);
printf("%d ", ST->Element); /* 访问取出队列的节点 */
if (ST->Left) Enqueue(ST->Left, Q);
if (ST->Right) Enqueue(ST->Right, Q);
}
}
/* 后增方法 */
queueli.h
这个队列是用来辅助树的层序遍历的
#include "tree.h"
typedef Position ElementType1;
/* START: fig3_57.txt */
#ifndef _Queueli_h
#define _Queueli_h
struct Node;
struct QNode;
typedef struct Node *PtrToNode; // 指向Node节点的指针
typedef struct QNode *Queue; // 队列头,也是指向QNode节点的指针
int IsEmpty(Queue Q);
Queue CreateQueue(void);
void DisposeQueue(Queue Q);
void MakeEmpty1(Queue Q);
void Enqueue(ElementType1 X, Queue Q);
ElementType1 Front(Queue Q);
void Dequeue(Queue Q);
ElementType1 FrontAndDequeue(Queue Q);
#endif /* _Queue_h */
/* END */
queueli.c
#include "queueli.h"
#include "fatal.h"
#include <stdio.h>
// #include "tree.h"
// 节点
struct Node
{
ElementType1 Element;
PtrToNode Next;
};
struct QNode
{
PtrToNode rear; // 指向队尾节点
PtrToNode front; // 指向对头节点
};
// 判断队列是否为空
int IsEmpty(Queue Q)
{
return (Q->front == NULL);
}
Queue CreateQueue(void)
{
Queue Q;
Q = malloc(sizeof(struct QNode));
if (Q == NULL)
FatalError("Out of space!!!"); // 空间用尽警告
Q->front = NULL;
Q->rear = NULL;
MakeEmpty1(Q); // 还是感觉有些多此一举
return Q;
}
// 创建一个空队列
void MakeEmpty1(Queue Q)
{
if (Q == NULL)
Error("Must use CreateQueue first");
else
while (!IsEmpty(Q))
Dequeue(Q);
}
// 清除队列
void DisposeQueue(Queue Q)
{
if (Q != NULL)
{
MakeEmpty1(Q);
free(Q);
}
}
// 入队操作
void Enqueue(ElementType1 X, Queue Q)
{
PtrToNode TmpCell;
TmpCell = malloc(sizeof(struct Node));
if (TmpCell == NULL)
FatalError("Out of space!!!");
TmpCell->Element = X;
TmpCell->Next = NULL;
if (Q->rear == NULL)
{ // 此时队列为空
Q->rear = TmpCell;
Q->front = TmpCell;
} else { // 不为空
Q->rear->Next = TmpCell; // 将节点入队
Q->rear = TmpCell; // rear 仍然保持最后
}
}
// 取出队首元素
ElementType1 Front(Queue Q)
{
if (!IsEmpty(Q))
return Q->front->Element;
Error("Empty queue");
return NULL; // Return value used to avoid warning
}
// 出队操作
void Dequeue(Queue Q)
{
PtrToNode FrontCell;
if (IsEmpty(Q))
Error("Empty queue");
else
{
FrontCell = Q->front;
if (Q->front == Q->rear) { // 只有一个元素
Q->front = Q->rear = NULL;
} else { // 有多个元素时
Q->front = Q->front -> Next; // 先将front指向队首元素的下一个元素
}
free(FrontCell); // 不要忘了释放出对的节点
}
}
// 在出队的同时返回该元素,即队首元素
ElementType1 FrontAndDequeue(Queue Q)
{
ElementType1 X = NULL;
if (IsEmpty(Q))
Error("Empty queue");
else
{
X = Front(Q);
Dequeue(Q);
}
return X;
}
main.c(测试函数)
#include "tree.h"
#include <stdio.h>
int main( )
{
SearchTree T;
Position P;
int i;
int j = 15;
T = MakeEmpty( NULL ); // 创建一棵空树
for( i = 0; i < 50; i++, j = ( j + 7 ) % 50 ) // 将 50 个数插入树中
T = Insert( j, T );
for( i = 0; i < 50; i++ )
if( ( P = Find( i, T ) ) == NULL || Retrieve( P ) != i ) // 测试查找函数
printf( "Error at %d\n", i );
/* 测试遍历 */
printf("先序遍历 \n");
PreOrderTraversal(T);
printf("\n");
printf("中序遍历 \n");
InOrderTraversal(T);
printf("\n");
printf("后序遍历 \n");
PostOrderTraversal(T);
printf("\n");
printf("层序遍历 \n");
LevelOrderTraversal(T);
printf("\n");
/* 测试遍历 */
for( i = 0; i < 50; i += 2 )
T = Delete( i, T ); // 以 1 为步长,作删除操作
// 测试删除操作是否成功
for( i = 1; i < 50; i += 2 )
if( ( P = Find( i, T ) ) == NULL || Retrieve( P ) != i )
printf( "Error at %d\n", i );
for( i = 0; i < 50; i += 2 )
if( ( P = Find( i, T ) ) != NULL )
printf( "Error at %d\n", i );
// 打印最大数和最小数
printf( "Min is %d, Max is %d\n", Retrieve( FindMin( T ) ),
Retrieve( FindMax( T ) ) );
return 0;
}
fatal.h(定义错误的函数)
#include <stdio.h>
#include <stdlib.h>
#define Error(Str) FatalError( Str )
#define FatalError(Str) fprintf( stderr, "%s\n", Str ), exit( 1 )