//对树的一些基本操作应按照处理森林的思想去理解,树是只有一棵树的森林
#include<iostream>
#include<malloc.h>
using namespace std;
#define QSIZE 20
typedef char ElemType;
typedef struct CSNode
{
ElemType data;
CSNode *pFchild;
CSNode *pNsibling;
}CSNode, *CSTree;
typedef struct Queue
{
CSTree *pBase;
int Front;
int Rear;
}Queue;
void InitQueue(Queue &Q)
{
Q.pBase = new CSTree[QSIZE];
Q.Front = 0;
Q.Rear = 0;
}
void DestroyQueue(Queue &Q)
{
delete[]Q.pBase;
Q.Front = 0;
Q.Rear = 0;
}
void ClearQueue(Queue &Q)
{
Q.Front = 0;
Q.Rear = 0;
}
bool QueueFull(Queue Q)
{
if ((Q.Rear + 1) % QSIZE == Q.Front)
return true;
else
return false;
}
bool QueueEmpty(Queue Q)
{
if (Q.Front == Q.Rear)
return true;
else
return false;
}
bool EnQueue(Queue &Q, CSTree e)
{
if (QueueFull(Q))
return false;
else
{
Q.pBase[Q.Rear] = e;
Q.Rear = (Q.Rear + 1) % QSIZE;
return true;
}
}
bool DeQueue(Queue &Q, CSTree &e)
{
if (QueueEmpty(Q))
return false;
else
{
e = Q.pBase[Q.Front];
Q.Front = (Q.Front + 1) % QSIZE;
return true;
}
}
bool GetHead(Queue Q, CSTree &e)
{
if (QueueEmpty(Q))
return false;
else
{
e = Q.pBase[Q.Front];
return true;
}
}
#define STACKSIZE 10
#define SIZEADD 5
typedef CSTree SElemType;
typedef struct Stack
{
SElemType *pBase;
SElemType *pTop;
int Stacksize;
}Stack;
void InitStack(Stack &S)
{
S.pBase = new SElemType[STACKSIZE];
S.pTop = S.pBase;
S.Stacksize = STACKSIZE;
}
void DestroyStack(Stack &S)
{
delete[]S.pBase;
S.pBase = NULL;
S.pTop = NULL;
S.Stacksize = 0;
}
void ClearStack(Stack &S)
{
S.pTop = S.pBase;
}
bool StackEmpty(Stack S)
{
if (S.pBase == S.pTop)
return true;
else
return false;
}
int StackLength(Stack S)
{
return S.pTop - S.pBase;
}
void VisitS(SElemType e)
{
cout << e->data << " ";
}
void Push(Stack &S, SElemType e)
{
if (S.pTop - S.pBase >= S.Stacksize)
{
S.pBase = (SElemType *)realloc(S.pBase, (SIZEADD + STACKSIZE)*sizeof(SElemType));
S.pTop = S.pBase + S.Stacksize;
S.Stacksize += SIZEADD;
}
*S.pTop++ = e;
}
bool Pop(Stack &S)
{
if (StackEmpty(S))
return false;
--S.pTop;
return true;
}
bool GetTop(Stack S, SElemType &e)
{
if (StackEmpty(S))
return false;
else
{
e = *(S.pTop - 1);
return true;
}
}
void StackDePrint(Stack S)
{
SElemType *p = S.pTop;
if (StackEmpty(S))
return;
while (p>S.pBase)
{
--p;
VisitS(*p);
}
cout << endl;
}
void StackAsPrint(Stack S)
{
SElemType *p = S.pBase;
if (StackEmpty(S))
return;
while (p < S.pTop)
{
VisitS(*p);
++p;
}
cout << endl;
}
void InitTree(CSTree &T)
{
T = NULL;
}
void CreateTree(CSTree &T)
{
ElemType array[20];
CSTree p, p1;
Queue Q;
int i, l;
InitQueue(Q);
printf("请输入根结点(字符型,空格为空): ");
cin >> array[0];
if (array[0])// 非空树
{
T = new CSNode;// 建立根结点
T->data = array[0];
T->pNsibling = NULL;//只是一棵树
EnQueue(Q, T);
while (!QueueEmpty(Q))
{
DeQueue(Q, p);
printf("请按长幼顺序输入结点%c的所有孩子: ", p->data);
gets_s(array);
l = strlen(array);
if (l > 0)
{
p->pFchild = new CSNode; // 建立长子结点
p1 = p->pFchild;
p1->data = array[0];
for (i = 1; i < l; ++i)
{
p1->pNsibling = new CSNode;// 建立下一个兄弟结点
EnQueue(Q, p1);
p1 = p1->pNsibling;
p1->data = array[i];
}
p1->pNsibling = NULL;//最后一个兄弟
}
else
p->pFchild = NULL;
}
}
else
T = NULL;
}
void DestroyTree(CSTree &T)
{
if (T)
{
if (T->pFchild)
DestroyTree(T->pFchild);
if (T->pNsibling)
DestroyTree(T->pNsibling);
delete T;
T = NULL;
}
}
#define ClearTree DestroyTree
bool TreeEmpty(CSTree T)
{
if (T)
return false;
else
return true;
}
int TreeDepth(CSTree T)
{
CSTree p;
int depth, max = 0;
if (!T)
return 0;
else if (!(T->pFchild))
return 1;
else
{
for (p = T->pFchild; p; p = p->pNsibling)
{
depth = TreeDepth(p);
if (depth > max)
max = depth;
}
return max + 1;
}
}
ElemType Value(CSTree p)
{
return p->data;
}
void VisitT(ElemType e)
{
cout << e;
}
ElemType Root(CSTree T)
{
if (T)
return Value(T);
else
return NULL;
}
CSTree GetPoint(CSTree T, ElemType e)
{
Queue Q;
CSTree p;
InitQueue(Q);
if (T)
{
EnQueue(Q, T);
while (!QueueEmpty(Q))
{
DeQueue(Q, p);
if (p->data == e)
return p;
if (p->pFchild)
EnQueue(Q, p->pFchild);
if (p->pNsibling)
EnQueue(Q, p->pNsibling);
}
}
return NULL;
}
bool Assign(CSTree &T, ElemType cur, ElemType e)
{
CSTree p;
if (T)
{
p = GetPoint(T, cur);
if (p)
{
p->data = e;
return true;
}
}
return false;
}
CSTree GetParent(CSTree T, ElemType e)
{
CSTree p, t;
Queue Q;
InitQueue(Q);
if (T)
{
if (Value(T) == e)//先处理根节点
return NULL;
EnQueue(Q, T);
while (!QueueEmpty(Q))
{
DeQueue(Q, p);
if (p->pFchild)
{
if (p->pFchild->data == e)//再处理根节点第一个孩子
return p;
t = p;
p = p->pFchild;
EnQueue(Q, p);
while (p->pNsibling)//最后处理根节点的其他孩子(除长子)
{
p = p->pNsibling;
if (Value(p) == e)
return t;
EnQueue(Q, p);
}
}
}
}
}
CSTree GetLeftChild(CSTree T, ElemType e)
{
CSTree f;
f = GetPoint(T, e);
if (f && f->pFchild)
return f->pFchild;
else
return NULL;
}
CSTree GetRightSibling(CSTree T, ElemType e)
{
//只处理相邻的第一个兄弟
CSTree f;
f = GetPoint(T, e);
if (f&&f->pNsibling)
return f->pNsibling;
else
return NULL;
}
bool InsertChild(CSTree &T, CSTree p, int i, CSTree c)
{ // 初始条件: 树T存在,p指向T中某个结点,1≤i≤p所指结点的度+1,非空树c与T不相交
// 操作结果: 插入c为T中p结点的第i棵子树
// 因为p所指结点的地址不会改变,故p不需是引用类型
int j;
if (T) // T不空
{
if (i == 1) // 插入c为p的长子
{
c->pNsibling = p->pFchild; // p的原长子现是c的下一个兄弟(c本无兄弟)
p->pFchild = c;
}
else // 找插入点
{
p = p->pFchild; // 指向p的长子
j = 2;
while (p&&j<i)
{
p = p->pNsibling;
++j;
}
if (j == i) // 找到插入位置
{
c->pNsibling = p->pNsibling;
p->pNsibling = c;//c做p的相邻右兄弟
}
else // p原有孩子数小于i-1
return false;
}
return true;
}
else // T空
return false;
}
bool DeleteChild(CSTree &T, CSTree p, int i)
{ // 初始条件: 树T存在,p指向T中某个结点,1≤i≤p所指结点的度
// 操作结果: 删除T中p所指结点的第i棵子树
// 因为p所指结点的地址不会改变,故p不需是引用类型
CSTree b;
int j;
if (T) // T不空
{
if (i == 1) // 删除长子
{
b = p->pFchild;
p->pFchild = b->pNsibling; // p的原次子现是长子
b->pNsibling = NULL;//断绝长子与次子的关系
DestroyTree(b);
}
else // 删除非长子
{
p = p->pFchild; // p指向长子
j = 2;
while (p&&j<i)
{
p = p->pNsibling;
++j;
}
if (j == i) // 找到第i棵子树
{
b = p->pNsibling;
p->pNsibling = b->pNsibling;//p的右兄弟更新为b的右兄弟
b->pNsibling = NULL;//断绝待删除孩子和紧挨该孩子的右兄弟的关系
DestroyTree(b);
}
else // p原有孩子数小于i
return false;
}
return true;
}
else
return false;
}
void PreOrder(CSTree T)
{//树先根遍历(森林先序遍历)
if (T)
{//按照森林先序遍历思想理解
VisitT(Value(T));
PreOrder(T->pFchild);
PreOrder(T->pNsibling);
}
}
void PostOrderPrint(CSTree T)
{ // 后根遍历孩子-兄弟二叉链表结构的树T
CSTree p;
if (T)
{
if (T->pFchild)// 有长子
{
PostOrderPrint(T->pFchild);// 后根遍历长子子树(处理长子)
p = T->pFchild->pNsibling; // p指向长子的下一个兄弟
while (p)
{//处理长子的所有兄弟也就是处理根除了长子之外的所有儿子
PostOrderPrint(p);// 后根遍历下一个兄弟子树
p = p->pNsibling;// p指向再下一个兄弟
}
}
VisitT(Value(T)); // 最后访问根结点
}
}
void LevelOrderPrint(CSTree T)
{// 层序遍历孩子-兄弟二叉链表结构的树T
CSTree p;
Queue Q;
InitQueue(Q);
if (T)
{
VisitT(Value(T));// 先访问根结点
EnQueue(Q, T);// 入队根结点的指针
while (!QueueEmpty(Q))// 队不空
{
DeQueue(Q, p); // 队头出队
if (p->pFchild)// 有长子
{
p = p->pFchild;
VisitT(Value(p));
EnQueue(Q, p);
while (p->pNsibling)//有下一个兄弟
{
p = p->pNsibling;
VisitT(Value(p));// 访问下一个兄弟
EnQueue(Q, p); // 入队兄弟结点的指针
}
}
}
}
}
void OutPathPrint(CSTree T, Stack &S)
{//森林思想
while (!T)//每一次循环处理完一棵树;如果是树的话,只一次循环;如果是森林,有几棵树则循环几次
{
Push(S, T);//当前树的根结点入栈
if (!T->pFchild)//如果当前结点无儿子,该结点必为叶子结点
StackAsPrint(S);
else
OutPathPrint(T->pFchild, S);//对其长子结点进行递归处理
Pop(S);//长子结点出栈
T = T->pNsibling;//寻找下一个兄弟(如果是树的话,且第一循环则根结点的右指针域为空,整个函数处理完毕)
}
}
int main(void)
{
Stack S;
CSTree T;
InitStack(S);
InitTree(T);
CreateTree(T);
LevelOrderPrint(T);
OutPathPrint(T, S);
return(0);
}
数据结构之树
最新推荐文章于 2022-11-21 16:31:29 发布
本文详细探讨了数据结构中的树,包括树的基本概念、类型、操作及其实现。从二叉树到多叉树,从查找、插入到删除操作,深入解析树在算法和计算机科学中的应用。通过实例分析,揭示了树如何优化数据存储和检索效率,为软件开发提供高效解决方案。
摘要由CSDN通过智能技术生成