Description
用函数实现如下二叉排序树算法: (1) 插入新结点 (2) 前序、中序、后序遍历二叉树 (3) 中序遍历的非递归算法 (4) 层次遍历二叉树 (5) 在二叉树中查找给定关键字(函数返回值为成功1,失败0) (6) 交换各结点的左右子树 (7) 求二叉树的深度 (8) 叶子结点数
输入格式
第一行:准备建树的结点个数n 第二行:输入n个整数,用空格分隔 第三行:输入待查找的关键字 第四行:输入待查找的关键字 第五行:输入待插入的关键字
输出格式
第一行:二叉树的先序遍历序列 第二行:二叉树的中序遍历序列 第三行:二叉树的后序遍历序列 第四行:查找结果 第五行:查找结果 第六行~第八行:插入新结点后的二叉树的先、中、序遍历序列 第九行:插入新结点后的二叉树的中序遍历序列(非递归算法) 第十行:插入新结点后的二叉树的层次遍历序列 第十一行~第十三行:第一次交换各结点的左右子树后的先、中、后序遍历序列 第十四行~第十六行:第二次交换各结点的左右子树后的先、中、后序遍历序列 第十七行:二叉树的深度 第十八行:叶子结点数
输入样例
7 40 20 60 18 50 56 90 18 35 30
输出样例
40 20 18 60 50 56 90 18 20 40 50 56 60 90 18 20 56 50 90 60 40 1 0 40 20 18 30 60 50 56 90 18 20 30 40 50 56 60 90 18 30 20 56 50 90 60 40 18 20 30 40 50 56 60 90 40 20 60 18 30 50 90 56 40 60 90 50 56 20 30 18 90 60 56 50 40 30 20 18 90 56 50 60 30 18 20 40 40 20 18 30 60 50 56 90 18 20 30 40 50 56 60 90 18 30 20 56 50 90 60 40 4 4
使用C语言模拟实现C++STL库内栈和队列的基本操作
代码如下:
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <stack>
#include <queue>
#include <assert.h>
using namespace std;
typedef int ElemType;// 定义二叉排序树元素类型
typedef struct BSTNode//二叉排序树的结点类型
{
ElemType data;
struct BSTNode* lchild;
struct BSTNode* rchild;
}BSTNode,*BSTree;
void BSTNodeInsert(BSTree& T, ElemType x)
{
//二叉排序树结点的插入
if (T == NULL)//开始树为空或者找到插入位置,递归结束
{
BSTNode* newnode = (BSTNode*)malloc(sizeof(BSTNode));
newnode->data = x;
newnode->lchild = NULL;
newnode->rchild = NULL;
T = newnode;
}
else//树不为空,查找插入位置
{
if (x > T->data)//大的向右
{
BSTNodeInsert(T->rchild, x);
}
else if (x < T->data)//小的向左
{
BSTNodeInsert(T->lchild, x);
}
}
}
void CreatBSTree(BSTree& T)
{
//构建n个结点的二叉排序树
int n = 0;
cin >> n;
while (n--)
{
ElemType val = 0;
cin >> val;
BSTNodeInsert(T, val);
}
}
void PreOrderTraverse(BSTree& T)
{
//二叉排序树的先序遍历(递归写法)
if (T!=NULL)
{
printf("%d ", T->data);
PreOrderTraverse(T->lchild);
PreOrderTraverse(T->rchild);
}
}
void InOrderTraverse(BSTree& T)
{
//二叉排序树的中序遍历(递归写法)
if (T != NULL)
{
InOrderTraverse(T->lchild);
printf("%d ", T->data);
InOrderTraverse(T->rchild);
}
}
void PostOrderTraverse(BSTree& T)
{
//二叉排序树的后序遍历(递归写法)
if (T != NULL)
{
PostOrderTraverse(T->lchild);
PostOrderTraverse(T->rchild);
printf("%d ", T->data);
}
}
typedef struct Stack
{
BSTree* base;// 在栈初始化和销毁之后,base的值为NULL
BSTree* top;// 栈顶指针
int capacity;// 当前已分配的存储空间,以元素为单位
}Stack;// 顺序栈
#define STACK_INIT_SIZE 100// 存储空间初始分配量
#define STACKINCREMENT 10// 存储空间分配增量
void StackInit(Stack& S)
{
//构造一个空栈S
S.base = S.top = NULL;
S.capacity = 0;
}
void StackPush(Stack& S, BSTree x)
{
// 在栈S中插入元素x为新的栈顶元素
if (S.top - S.base == S.capacity)//栈的容量已满
{
//扩容
int newCapacity = S.capacity == 0 ? STACK_INIT_SIZE : S.capacity + STACKINCREMENT;//首次分配空间为STACK_INIT_SIZE,之后每次增加STACKINCREMENT
BSTree* tmp = (BSTree*)realloc(S.base,sizeof(BSTree) * newCapacity);
if (tmp == NULL)
{
cout << "StackPush malloc failed" << endl;
exit(-1);
}
S.base = tmp;
S.top = S.base + S.capacity;
S.capacity = newCapacity;
}
*S.top = x;//插入元素
S.top++;
}
bool StackEmpty(Stack& S)
{
//判断栈S是否为空,为空返回true,不为空返回false
return S.top - S.base == 0;
}
void StackPop(Stack& S)
{
// 若栈不空,则删除S的栈顶元素
assert(!StackEmpty(S));
S.top--;
}
size_t StackSize(Stack& S)
{
// 返回栈S的元素个数
return S.top - S.base;
}
BSTree StackTop(Stack& S)
{
// 若栈不空,则返回S的栈顶元素
assert(!StackEmpty(S));
return *(S.top - 1);
}
void StackDestroy(Stack& S)
{
//销毁栈S
free(S.base);
S.base = S.top = NULL;
S.capacity = 0;
}
void InOrderTraverse_by_Stack(BSTree& T)
{
//二叉排序树的中序遍历(非递归写法),借助栈来实现
Stack S;
StackInit(S);
BSTree cur = T;
while (cur != NULL || !StackEmpty(S))//当前结点为空且栈为空,结束循环
{
while (cur)//向左走到尽头,将沿途结点压进栈
{
StackPush(S, cur);//根结点进栈
cur = cur->lchild;//遍历左子树
}
cur = StackTop(S);//根结点出栈
printf("%d ", cur->data);
cur = cur->rchild;//遍历右子树
StackPop(S);
}
StackDestroy(S);
}
typedef struct QueueNode
{
BSTree ptr;
struct QueueNode* next;
}QueueNode;//链式队列的结点类型
typedef struct Queue
{
QueueNode* head;//队列头指针
QueueNode* tail;//队列尾指针
}Queue;//链式队列
void QueueInit(Queue& Q)
{
//构造一个空队列Q
Q.head = Q.tail = NULL;
}
void QueuePush(Queue& Q, BSTree x)
{
// 在队列Q中插入元素x为新的队尾元素
QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
if (newnode == NULL)
{
cout << "QueuePush malloc failed" << endl;
exit(-1);
}
newnode->ptr = x;
newnode->next = NULL;
//插入元素
if (Q.head == NULL)//队列为空
{
Q.head = newnode;
Q.tail = newnode;
}
else//队列已有元素
{
Q.tail->next = newnode;
Q.tail = newnode;
}
}
bool QueueEmpty(Queue& Q)
{
//判断队列Q是否为空,为空返回true,不为空返回false
return Q.head == NULL;
}
void QueuePop(Queue& Q)
{
//若队列Q不为空,删除队头元素
assert(!QueueEmpty(Q));
QueueNode* next = Q.head->next;
free(Q.head);
Q.head = next;
if (Q.head == NULL)//当队列删为空,把tail置为空,防止野指针
{
Q.tail = NULL;
}
}
BSTree QueueFront(Queue& Q)
{
//若队列Q不为空,返回队头元素
assert(!QueueEmpty(Q));
return Q.head->ptr;
}
BSTree QueueBack(Queue& Q)
{
//若队列Q不为空,返回队尾元素
assert(!QueueEmpty(Q));
return Q.tail->ptr;
}
size_t QueueSize(Queue& Q)
{
//返回队列Q的元素个数
size_t size = 0;
QueueNode* cur = Q.head;
while (cur != NULL)
{
size++;
}
return size;
}
void QueueDestroy(Queue& Q)
{
//销毁队列
QueueNode* cur = Q.head;
while (cur != NULL)
{
QueueNode* next = cur->next;
free(cur);
cur = next;
}
Q.head = Q.tail = NULL;
}
void LevelTraverse(BSTree& T)
{
//二叉排序树的层次遍历,借助队列来实现
Queue Q;
QueueInit(Q);
if (T != NULL)//开始树不为空
{
QueuePush(Q, T);
}
while (!QueueEmpty(Q))//队列不为空
{
BSTree cur = QueueFront(Q);//取队头元素
printf("%d ", cur->data);
if (cur->lchild != NULL)//左子树不为空,左子树入队
{
QueuePush(Q, cur->lchild);
}
if (cur->rchild != NULL)//右子树不为空,右子树入队
{
QueuePush(Q, cur->rchild);
}
QueuePop(Q);//已遍历完成的结点出队
}
QueueDestroy(Q);
}
int BSTreeSearch(BSTree& T, ElemType x)
{
//二叉排序树的查找,找到返回1,没找到返回0
if (T == NULL)//开始树为空或者查找到尽头,查找失败,返回0
{
return 0;
}
else if (T->data == x)//查找成功,返回1
{
return 1;
}
else if (x > T->data)//大于向右找
{
return BSTreeSearch(T->rchild, x);
}
else if (x < T->data)//小于向左找
{
return BSTreeSearch(T->lchild, x);
}
}
void SubTreeSwap(BSTree& T)
{
//交换各结点的左右子树
if (T != NULL && (T->lchild != NULL || T->rchild != NULL))//当前结点不为空,且左右子树不全为空
{
//交换当前结点的左右子树
BSTree tmp = T->lchild;
T->lchild = T->rchild;
T->rchild = tmp;
SubTreeSwap(T->lchild);//交换当前结点左子树的左右子树
SubTreeSwap(T->rchild);//交换当前结点右子树的左右子树
}
}
size_t Depth(BSTree& T)
{
//二叉树的深度
if (T == NULL)//空树返回0,不能省略
{
return 0;
}
else
{
size_t m = Depth(T->lchild);//左子树深度
size_t n = Depth(T->rchild);//右子树深度
return m > n ? m + 1 : n + 1;//当前结点深度=左右子树中较大的一个+1
}
}
size_t LeafNumbers(BSTree& T)
{
if (T == NULL)//空树返回0,不能省略
{
return 0;
}
else
{
if (T->lchild == NULL && T->rchild == NULL)//当前结点是叶子结点,返回1
{
return 1;
}
else
{
return LeafNumbers(T->lchild) + LeafNumbers(T->rchild);//当前结点不是叶子结点,统计左右子树的叶子结点之和
}
}
}
void BSTreeDestory(BSTree& T)
{
//销毁二叉树
if (T != NULL)
{
BSTree left = T->lchild;
BSTree right = T->rchild;
free(T);
T = NULL;
BSTreeDestory(left);
left = NULL;
BSTreeDestory(right);
right = NULL;
}
}
int main()
{
BSTree T=NULL;
//构建二叉排序树
CreatBSTree(T);
//先序遍历(递归写法)
PreOrderTraverse(T);
cout << endl;
//中序遍历(递归写法)
InOrderTraverse(T);
cout << endl;
//后序遍历(递归写法)
PostOrderTraverse(T);
cout << endl;
int x = 0;
cin >> x;//查找x
cout << BSTreeSearch(T, x) << endl;
cin >> x;//查找x
cout << BSTreeSearch(T, x) << endl;
cin >> x;//插入x
BSTNodeInsert(T, x);
//先序遍历(递归写法)
PreOrderTraverse(T);
cout << endl;
//先序遍历(递归写法)
InOrderTraverse(T);
cout << endl;
//后序遍历(递归写法)
PostOrderTraverse(T);
cout << endl;
//中序遍历(非递归写法)
InOrderTraverse_by_Stack(T);
cout << endl;
//层次遍历
LevelTraverse(T);
cout << endl;
//交换左右子树
SubTreeSwap(T);
//先序遍历(递归写法)
PreOrderTraverse(T);
cout << endl;
//中序遍历(递归写法)
InOrderTraverse(T);
cout << endl;
//后序遍历(递归写法)
PostOrderTraverse(T);
cout << endl;
//交换左右子树
SubTreeSwap(T);
//先序遍历(递归写法)
PreOrderTraverse(T);
cout << endl;
//中序遍历(递归写法)
InOrderTraverse(T);
cout << endl;
//后序遍历(递归写法)
PostOrderTraverse(T);
cout << endl;
//树的深度
cout << Depth(T) << endl;
//树的叶子结点数
cout << LeafNumbers(T) << endl;
//销毁二叉树
BSTreeDestory(T);
return 0;
}