#include <iostream>
#include <string>
using namespace std;
typedef char Etype;
struct EType {
Etype key;
};
struct BinaryTreeNode {
EType data;
BinaryTreeNode* LChird;//左孩地址
BinaryTreeNode* RChird;//右孩地址
};
typedef BinaryTreeNode* BinaryTree;
//前序遍历:首先访问根节点,然后遍历左子树,最后遍历右子树
void PreOrderRecursive(BinaryTreeNode* BT) {
//二叉树遍历递归算法
if (BT) {
cout << BT->data.key << endl;
PreOrderRecursive(BT->LChird);
PreOrderRecursive(BT->RChird);
}
}
//中序遍历:首先遍历左子树,然后访问根节点,最后遍历右子树
void InOrderRecursive(BinaryTreeNode* BT) {
//二叉树遍历递归算法
if (BT) {
InOrderRecursive(BT->LChird);
cout << BT->data.key << endl;
InOrderRecursive(BT->RChird);
}
}
//后序遍历:首先遍历左子树,然后遍历右子树,最后访问根节点
void PostOrderRecursive(BinaryTreeNode* BT) {
//二叉树遍历递归算法
if (BT) {
PostOrderRecursive(BT->LChird);
PostOrderRecursive(BT->RChird);
cout << BT->data.key << endl;
}
}
//前序遍历的非递归算法
struct SType {
BinaryTreeNode* ptr;
bool status;
};
struct Stack {
SType* element;
int top;
int maxsize;
};
//创建空堆栈
void CreateStack(Stack& S, int MaxStackSize) {
S.maxsize = MaxStackSize;
S.element = new SType[S.maxsize];//创建数组元素
S.top = -1;//top指向的是数据空间的第一个元素,本身的值代表数据元素的下表,空表设top为-1
}
//判断堆栈是否为空
bool IsEmpty(Stack& S) {
if (S.top == -1) return true;
else return false;
}
//出栈操作,将栈顶元素取出,并且将top指向下一个元素的位置
bool Pop(Stack& S, SType& result) {
if (IsEmpty(S)) return false;
result = S.element[S.top];
S.top--;//栈顶指向下一个元素地址
return true;
}
//进栈操作,将top+1,输入元素存入新的栈顶
bool Push(Stack& S, SType& x) {//传入的是x的地址
if (IsEmpty(S)) return false;
S.top++;
S.element[S.top] = x;
return true;
}
//前序遍历:首先访问根节点,然后遍历左子树,最后遍历右子树
void PreOrderNoRecursive(BinaryTreeNode* BT) {
//二叉树遍历递归算法
Stack S;
SType temp;
BinaryTreeNode* p = BT;//p指向根节点data
int MaxStackSize = 50;
CreateStack(S, MaxStackSize);//产生一个空栈
while (p || IsEmpty(S)) {
if (p) {
cout << p->data.key << endl;//访问根节点
temp.ptr = p;
Push(S, temp);//根节点指针进栈S,以后回溯时再退栈
p = p->LChird;//指针指向访问过根节点的左子树
}
else {//左子树为空时,利用堆栈回溯
if (!IsEmpty(S)) {
Pop(S, temp);//从堆栈中弹出回溯节点指针
p = temp.ptr;
p = p->RChird;//指针指向回溯节点的右子树
}
}
}
}
//中遍历:首先遍历左子树,然后访问根节点,最后遍历右子树
void InOrderNoRecursive(BinaryTreeNode* BT) {
//二叉树遍历递归算法
Stack S;
SType temp;
BinaryTreeNode* p = BT;//p指向根节点data
int MaxStackSize = 50;
CreateStack(S, MaxStackSize);//产生一个空栈
while (p || IsEmpty(S)) {
while (p) {//找到最左子树
temp.ptr = p;
Push(S, temp); //根节点进栈,以后回溯时再退栈
p = p->LChird; //指针指向左子树
}
if (!IsEmpty(S)) {//左子树为空,利用堆栈回溯
Pop(S, temp);//从堆栈中弹出回溯节点指针
p = temp.ptr;
cout << p->data.key << endl;//访问根节点
p = p->RChird; //指针指向回溯节点的右子树
}
}
}
//后序遍历:首先遍历左子树,然后遍历右子树,最后访问根节点
void InOrderNoRecursive(BinaryTreeNode* BT) {
//二叉树遍历递归算法
Stack S;
SType temp;
BinaryTreeNode* p = BT;//p指向根节点data
int MaxStackSize = 50;
CreateStack(S, MaxStackSize);//产生一个空栈
while (p || IsEmpty(S)) {
if (p) {
//找到左子树
temp.status = false;//准备进栈节点进栈标志设为第一次进栈
temp.ptr = p;
Push(S, temp);//根节点进栈,以后回溯时再退栈
p = p->LChird;//指针指向左子树
}
else {
if (!IsEmpty(S)) {
Pop(S, temp);//从堆栈中弹出回溯节点指针及其标志位
p = temp.ptr;
if (temp.status) {
cout << p->data.key << endl;//访问该节点
p = NULL;
}
}
else {
temp.status = true;//改变进栈标志位,准备重新进栈
Push(S, temp);
p = p->RChird; //指针指向右孩
}
}
}
}
//二叉树层次访问遍历操作
struct QType {
BinaryTreeNode* ptr;
};
struct Queue {
QType* element;
int front;
int rear;
int maxsize;
};
//构造空队列算法
void CreatQueue(Queue& Q, int MaxQueueSize) {
Q.maxsize = MaxQueueSize;
Q.element = new QType[Q.maxsize];
Q.front = 0;
Q.rear = 0;
}
//判断队列是否为空
bool IsEmpty(Queue& Q) {
if (Q.front == Q.rear) return true;
return false;
}
//判断队列是否满了front=real+1;
bool IsFull(Queue& Q) {
if (Q.front == (Q.rear + 1) % (Q.maxsize + 1)) return true;
return false;
}
//返回队头元素的值
bool GetFront(Queue& Q, QType& result) {
//将font后面一个位置的队列元素的值取出
if (IsEmpty(Q)) return false;
result = Q.element[(Q.front + 1) % (Q.maxsize + 1)];
return true;
}
//进队运算
//将一个新的的元素x存储到当前real所指空间的下一个位置,首先要判断队列是否为满了
bool EnQueue(Queue& Q, QType& x) {
if (IsFull(Q)) return false;
Q.rear = (Q.rear + 1) % (Q.maxsize + 1); //real指向空间的下一个位置
Q.element[Q.rear] = x;//存入x
return true;
}
//出队运算
//将front所指空间的下一个位置的元素取出,首先要判断队列是否为空
bool OutQueue(Queue& Q, QType& result) {
if (IsEmpty(Q)) return false;
Q.front = (Q.front + 1) % (Q.maxsize + 1); //front指向空间的下一个位置
result = Q.element[Q.front];
return true;
}
//从上到下,从左到右遍历二叉树
void LevelOrder_LtoR_UtoD(BinaryTreeNode* BT) {
Queue Q;
QType temp;
BinaryTreeNode* p;
int MaxQueueSize = 50;
CreatQueue(Q, MaxQueueSize);//产生一个空队列
p = BT;//p指向根节点
temp.ptr = p;
EnQueue(Q, temp);//根节点进队
while (p) {
if (!OutQueue(Q, temp)) return; //出队失败,队列为空
p = temp.ptr;
cout << p->data.key << endl;//第一次进入while,输出根节点
if (p->LChird) {//左孩不为空
temp.ptr = p->LChird;
EnQueue(Q, temp);//左孩进队
}
if (p->RChird) {//右孩不为空
temp.ptr = p->RChird;
EnQueue(Q, temp);//右孩进队
}
}
}
//从上到下,从右到左遍历二叉树
void LevelOrder_RtoL_UtoD(BinaryTreeNode* BT) {
Queue Q;
QType temp;
BinaryTreeNode* p;
int MaxQueueSize = 50;
CreatQueue(Q, MaxQueueSize);//产生一个空队列
p = BT;//p指向根节点
temp.ptr = p;
EnQueue(Q, temp);//根节点进队
while (p) {
if (!OutQueue(Q, temp)) return; //出队失败,队列为空
p = temp.ptr;
cout << p->data.key << endl;//第一次进入while,输出根节点
if (p->RChird) {//右孩不为空
temp.ptr = p->RChird;
EnQueue(Q, temp);//右孩进队
}
if (p->LChird) {//左孩不为空
temp.ptr = p->LChird;
EnQueue(Q, temp);//左孩进队
}
}
}
//构造二叉树节点
BinaryTreeNode* MakeNode(EType& x) {
BinaryTreeNode* ptr;
ptr = new BinaryTreeNode;
if (!ptr) return NULL;
ptr->data = x;
ptr->LChird = NULL;
ptr->RChird = NULL;
return ptr;
}
//构造一个二叉树子树
void MakeBinaryTree(BinaryTreeNode* root,
BinaryTreeNode* left,
BinaryTreeNode* right) {
//链接root,left,right所指向节点的二叉树
root->LChird = left;
root->RChird = right;
}
//求二叉树的高度
int BinaryHeight(BinaryTreeNode* BT) {
if (!BT) return 0;//根节点为空
int HighL = BinaryHeight(BT->LChird);
int HighR = BinaryHeight(BT->RChird);
if (HighL > HighR)
return ++HighL;
else
return ++HighR;
}
//删除二叉树
void DeleteBinaryTree(BinaryTreeNode* BT) {
if (BT)
{
DeleteBinaryTree(BT->LChird);
DeleteBinaryTree(BT->RChird);
delete BT;
}
}
//分类二叉树运算
//分类二叉树中查找关键字为searchkey的节点值x算法
bool SortBinaryTreeSearch(BinaryTreeNode *BT,EType &x,int &SearchKey) {
BinaryTreeNode* p = BT;//定一个p指针,指向根节点
while (p) {
if (SearchKey < p->data.key) {
p = p->LChird;
}
else {
if (SearchKey < p->data.key) {
p = p->RChird;
}
else {
x = p->data;
return true;
}
}
}
return false;
}
//分类二叉树中插入关键字为searchkey的节点值x算法
bool SortBinaryTreeSearch(BinaryTreeNode* BT, EType& x) {
BinaryTreeNode* p = BT;
BinaryTreeNode* parent = NULL;//指向p的双亲
//求如果不重复出现,则插入节点x
while (p) {
parent = p;
if (x.key < p->data.key)
p = p->LChird;
else
if (x.key > p->data.key)
p = p->RChird;
else
return false;
}
插入时允许插入相同值的节点
//while (p)
//{
// parent = p;
// if (x.key < p->data.key)
// p = p->LChird;
// else
// p = p->RChird;
//}
//找到插入点,为x申请一个空间填入其值,并将该节点连接至parent
BinaryTreeNode* q = new BinaryTreeNode;
q->data = x;
q->LChird = NULL;
q->RChird = NULL;
if (BT) {
if (x.key < parent->data.key)
parent->LChird = q;
else
parent->RChird = q;
}
else
BT = q;//插入到空树中
return true;
}
//删除分类二叉树中插入关键字为searchkey的节点值x算法
BinaryTreeNode *SortBinaryTreeDelete(BinaryTreeNode* BT, int& SearchKey) {
//删除关键字为searchkey的节点,并返回删除后的根节点指针
BinaryTreeNode* p = BT, * parent = NULL;//p指向根节点,parent指向p的双亲
BinaryTreeNode* son, * ps;//ps指向son的双亲
while (p && p->data.key != SearchKey) {
//寻找被删节点值,并由p指向
parent = p;
if (SearchKey < p->data.key) {
p = p->LChird;
}
else {
p = p->RChird;
}
}
if (!p) {
cout << "没找到要删除的节点" << endl;
return BT;
}
//对二叉树重构
if (p->LChird&&p->RChird) {
//被删除节点存在两个子树,在p的左子树中查找最大元素最右子孙,并用此节点值替换被删除节点
//的值。替换后,将删除操作改变为从删除找到最大元素(最右子孙)
son = p->LChird;//删除节点的左孩子
ps = p;//删除节点
while (son->RChird) {
//son推进到p的左子树中最大元素(最右子孙)
ps = son;//
son = son->RChird;
}
p->data = son->data;//左子树中最大元素的值移动到p中
p = son; parent = ps;
//被删除节点转换为左子树中最大元素,所以p值为son,parent指向son的双亲
}
if (p->LChird)//p最多只有一个孩子,p指向这个孩子节点;p没有孩子,p为空
{
son = p->LChird;
}
else {
son = p->RChird;
}
if (p == BT)
BT = son;//被删除节点p是分类二叉树的跟,修改BT指向的孩子节点
else
{
//p只有一个孩子,判断p是parent的左孩子还是右孩子
if (p == parent->LChird)
parent->LChird = son;
else
parent->RChird = son;
}
delete p;
return BT;
}
struct MaxHeap {
Etype* heap;
int HeapSize;
int MaxSize;
};
//初始化一个非空的最大堆算法
void MaxHeapInit(MaxHeap& H) {
//从堆中的数据初始化一个最大堆
for (int i = H.HeapSize / 2; i >= 1; i--){
H.heap[0] = H.heap[i];//将子树根节点的值复制到工作空间heap[0]
int son = 2 * i;
while (son <= H.HeapSize) {
//找到左右孩中较大的节点
//son <= H.HeapSize时,存在右孩子,如果左孩子小于右孩子,son指向右孩子
if (son < H.HeapSize && (H.heap[son] < H.heap[son + 1])) {
son++;
}
//大孩子与工作空间的节点值再比较,工作空间的值较大,找到Heap[0]的目标位置
if (H.heap[0] >= H.heap[son]) break;
H.heap[son / 2] = H.heap[son];//将大孩子上移动到双亲位子
son *= 2;//son下移一层到上移的节点(大孩子位置)
}
H.heap[son / 2] = H.heap[0];//heap[0]存放的到目标位置
}
}
bool MaxHeapInsert(MaxHeap& H, Etype& x) {
//插入值为x的节点,到最大堆中,maxsize是数组最大的容量
if (H.HeapSize == H.MaxSize)
return false;//数据空间已满
int i = ++H.HeapSize;//i为插入节点后的节点个数
while (i != 1 && x > H.heap[i / 2]) {
H.heap[i] = H.heap[i / 2];
i = i / 2;//节点下移
}
H.heap[i] = x;
return true;
}
//最大堆中删除堆顶节点,并放入x中算法
bool MaxHeapDelete(MaxHeap& H,Etype &x) {
if (H.HeapSize == 0) return false;
x = H.heap[1];//最大节点存放到x
H.heap[0] = H.heap[H.HeapSize--];//最后一个节点放在heap[0],调整堆中元素的个数
int i = 1, son = 2 * i;
while (son <= H.HeapSize) {
//找到左右孩中较大的节点
//son <= H.HeapSize时,存在右孩子,如果左孩子小于右孩子,son指向右孩子
if (son < H.HeapSize && (H.heap[son] < H.heap[son + 1])) {
son++;
}
//大孩子与工作空间的节点值再比较,工作空间的值较大,找到Heap[0]的目标位置
if (H.heap[0] >= H.heap[son]) break;
H.heap[i] = H.heap[son];//孩子上移
i = son; //下移节点指针,继续比较
son *= 2;//son下移一层到上移的节点(大孩子位置)
}
H.heap[i] = H.heap[0];//heap[0]存放的到目标位置
return true;
}
//堆排序
void HeapSort(MaxHeap& H) {
//利用堆对H.heap[1:n]数组中的数据排序
Etype x;
MaxHeapInit(H);
for (int i = H.HeapSize - 1; i >= 1; i--) {
MaxHeapDelete(H,x);
H.heap[i + 1] = x;
}
}
深入理解数据结构——二叉树应用
最新推荐文章于 2022-05-29 18:49:12 发布