#include <stdio.h>
#include <stdlib.h>
typedef char ElemType;
typedef struct BNode
{
ElemType data;
struct BNode *lchild;
struct BNode *rchild;
}BNode,*BiTree;
/*
先序遍历
*/
void preOrd(BiTree T)
{
if(T != NULL)
{
printf("%c ",T->data);
preOrd(T->lchild);
preOrd(T->rchild);
}
}
/*
中序遍历
*/
void inOrd(BiTree T)
{
if(T != NULL)
{
inOrd(T->lchild);
printf("%c ",T->data);
inOrd(T->rchild);
}
}
/*
后序遍历
*/
void postOrd(BiTree T)
{
if(T != NULL)
{
postOrd(T->lchild);
postOrd(T->rchild);
printf("%c ",T->data);
}
}
/*
使用先序遍历的类似方法建立一棵二叉树
*/
//BNode *preCre()
//{
// BNode *T = NULL;
// ElemType enter;
// enter = getchar();//输入字符,需要空格的时候可输入空格,scanf遇到空格就结束输入了
// while(enter != '@')
// {
// T = (BNode *)malloc(sizeof(BNode));
// T->data = enter;
//
// T->lchild = preCre();
// T->rchild = preCre();
// }
// return T;
//}
/*
输入先序序列和中序序列创建一棵二叉树。
*/
//BNode *createBiTree(ElemType preArr[],int preStart,int preEnd,
// ElemType inArr[],int inStart,int inEnd)
//{
// if(preStart > preEnd)//判断子树是否为空
// {
// return NULL;
// }
// BNode *t = (BNode *)malloc(sizeof(BNode));
// t->data = preArr[preStart];
// int rIndex = inStart;
// while(rIndex < inEnd)
// {
// if(inArr[rIndex] == t->data)
// {
// break;
// }
// rIndex++;
// }
// int len = rIndex - inStart;
// t->lchild = createBiTree(preArr,preStart + 1,preStart + len,
// inArr,inStart,rIndex - 1);
// t->rchild = createBiTree(preArr,preStart + len + 1,preEnd,
// inArr,rIndex + 1,inEnd);
// return t;
//}
/*
输入层次遍历序列和中序序列创建一棵二叉树。
*/
#define MAX_SIZE 100
BNode *createBiTree(ElemType levArr[],int levStart,int levEnd,
ElemType inArr[],int inStart,int inEnd)
{
if(levStart > levEnd)//判断子树是否为空
{
return NULL;
}
BNode *t = (BNode *)malloc(sizeof(BNode));//创建根节点
t->data = levArr[levStart];//
int rIndex = inStart;
while(rIndex < inEnd)//寻找根结点在中序序列中的位置
{
if(inArr[rIndex] == t->data)
break;
rIndex++;
}
char lArr[MAX_SIZE] = {0};//将左子树存入数组
int lArrLen = 0;
for(int i = levStart + 1;i <= levEnd;i++)
{
for(int j = inStart;j < rIndex;j++)
{
if(levArr[i] == inArr[j])
{
lArr[lArrLen] = levArr[i];
lArrLen++;
}
}
}
char rArr[MAX_SIZE] = {0};//将右子树存入数组
int rArrLen = 0;
for(int i = levStart + 1;i <= levEnd;i++)
{
for(int j = rIndex + 1;j <= inEnd;j++)
{
if(levArr[i] == inArr[j])
{
rArr[rArrLen] = levArr[i];
rArrLen++;
}
}
}
t->lchild = createBiTree(lArr,0,lArrLen - 1,
inArr,inStart,rIndex - 1);
t->rchild = createBiTree(rArr,0,rArrLen - 1,
inArr,rIndex + 1,inEnd);
return t;
}
/*
求一棵二叉树的结点个数。
*/
int getNodes(BiTree T)
{
if(T == NULL)
{
return 0;
}
return 1 + getNodes(T->lchild) + getNodes(T->rchild);
}
/*
查找二叉树中值为x的结点。若存在,则返回存储位置,不存在,则返回空值
*/
BNode *getXNode(BiTree T,ElemType x)
{
if(T == NULL)
{
return NULL;
}
if(T->data == x)
{
return T;
}
BNode *lNode = getXNode(T->lchild,x);
if(lNode == NULL)
{
return getXNode(T->rchild,x);
}
return lNode;
}
/*
求二叉树的高度
*/
int getHeight(BiTree T)
{
if(T == NULL)
{
return 0;
}
int lHeight = getHeight(T->lchild);
int rHeight = getHeight(T->rchild);
if(lHeight > rHeight)
{
return 1 + lHeight;
}
return 1 + rHeight;
}
/*
求一棵二叉树中值为x的结点作为根结点的子树深度。
*/
int getXHeight(BiTree T,ElemType x)
{
BNode *xNode = getXNode(T,x);
getHeight(xNode);
}
/*
交换一棵二叉树的左右子树。
*/
void swiLRChild(BiTree T)
{
if(T != NULL)
{
BNode *temp = T->lchild;
T->lchild = T->rchild;
T->rchild = temp;
swiLRChild(T->lchild);
swiLRChild(T->rchild);
}
}
/*
判断两棵树是否相似,相似返回TRUE,不相似返回FALSE。
*/
#define TRUE 1
#define FALSE 0
int isSimilar(BiTree T1,BiTree T2)
{
if(T1 == NULL && T2 == NULL)
{
return TRUE;
}
else if(T1 != NULL && T2 != NULL)
{
return isSimilar(T1->lchild,T2->lchild) && isSimilar(T1->rchild,T2->rchild);
}
else
{
return FALSE;
}
}
/*
求一棵二叉树中的叶子结点个数
*/
int getLeafNode(BiTree T)
{
if(T == NULL)
{
return 0;
}
if(T->lchild == NULL && T->rchild == NULL)
{
return 1;
}
return getLeafNode(T->lchild) + getLeafNode(T->rchild);
}
/*
设计算法利用叶子结点中的空指针域将所有叶子结点链接成一个带头结点的双链表
*/
void leDouLi(BiTree T,BNode *&pTail)
{
if(T != NULL)
{
if(T->lchild == NULL && T->rchild == NULL)
{
//T->rchild = pTail->rchild;
pTail->rchild = T;
T->lchild = pTail;
pTail = pTail->rchild;
}
else
{
leDouLi(T->lchild,pTail);
leDouLi(T->rchild,pTail);
}
}
}
void operFunc(BiTree T)
{
BNode *L = (BNode *)malloc(sizeof(BNode));
L->lchild = NULL;
L->rchild = NULL;
BNode *pTail = L;
leDouLi(T,pTail);
BNode *curNode = L->rchild;
while(curNode != NULL)
{
printf("%c ",curNode->data);
curNode = curNode->rchild;
}
printf("\n");
}
/*
假设一个仅含二元运算的算数表达式以二叉链表形式存放在二叉树T,设计算法求解算术表达式的值
*/
int operaFunc(char calc,int lRes,int rRes)
{
switch(calc)
{
case '+':return lRes + rRes;break;
case '-':return lRes - rRes;break;
case '*':return lRes * rRes;break;
case '/':return lRes / rRes;break;
}
}
int getValue(BiTree T)
{
if(T == NULL)
{
return -999999;
}
if(T->lchild == NULL && T->rchild == NULL)
{
return T->data - '0';
}
else
{
int lRes = getValue(T->lchild);
int rRes = getValue(T->rchild);
return operaFunc(T->data,lRes,rRes);
}
}
/*
队列
*/
//#define MAX_SIZE 100
//typedef BNode * QElemType;
//
//typedef struct Queue
//{ //该指针用于指向存储二叉树中每个结点地址的数组,该数组中的每个元素是一个地址
// QElemType *pList;
// int front; //列头
// int rear; //队尾,牺牲一个存储单元来表示队列满和空
//}Queue;
//
对队列进行初始化
//void initailQueue(Queue &Q)
//{
// //用pList指向一个用于存储结点地址的顺序表
// Q.pList = (QElemType *) malloc(sizeof(QElemType) * MAX_SIZE);
// //这个特殊的顺序表只能在rear存入数据,且rear永远指向下一个存储数据的空白单元
// //front指向已经存储进去的元素,且front永远指向未来第一个要出队列的数据所在单元,
// //队列为空时,front指向rear(空白数据单元)
// Q.rear = 0; //当前队列为空,所以下一个存储内容的单元索引为零
// Q.front = 0; //当前队列为空,约定rear = front = 0
//}
//
//void enQueue(Queue &Q, QElemType e)
//{
// //进队列时先应该判断是否满,插入的位置是在rear,
// //入队列后,rear存储数据将要移到下一个位置pos,如果pos是front,则rear = front
// //因为之前规定front = rear为队空,但是实际上队列是满的,为了解决这种矛盾,
// //将(rear + 1) % MAX_SIZE = front视为队列满了,也就是不能再存入数据,牺牲掉一个空白单元
// int nextInsrtPos = (Q.rear + 1) % MAX_SIZE;
//
// //在rear当前指向的存储单元写入数据
// Q.pList[Q.rear] = e;
// Q.rear = nextInsrtPos; //移向下一个待写入数据的空白单元
//}
//
//void deQueue(Queue &Q, QElemType *e)
//{
// *e = Q.pList[Q.front];//取出元素内容
// Q.front = (Q.front + 1) % MAX_SIZE; //往后移动一个位置
//}
//
//int isEmptyQueue(Queue Q)
//{
// if (Q.front == Q.rear)
// return 1;
// else
// return 0;
//}
//
//
/*
二叉树的层次遍历。
*/
//void levOrd(BiTree T)
//{
// Queue Q;
// initailQueue(Q);//初始化队列
// enQueue(Q,T);//将根结点压入队列
// while(!isEmptyQueue(Q))//访问队列中的元素
// {
// BNode *e = NULL;
// deQueue(Q,&e);//出队列
// printf("%c ",e->data);//输出根结点的值
// //将左右依次孩子压入队列
// if(e->lchild != NULL)
// {
// enQueue(Q,e->lchild);
// }
// if(e->rchild != NULL)
// {
// enQueue(Q,e->rchild);
// }
// }
//}
/*
判断一棵树是否为完全二叉树
*/
//int isComplete(BiTree T)
//{
// Queue Q;//定义一个队列
// initailQueue(Q);//初始化队列
// enQueue(Q,T);//将根结点压入队列
// while(!isEmptyQueue)//访问队列中的元素
// {
// BNode *e = NULL;
// deQueue(Q,&e);
// if(e == NULL)
// {
// break;
// }
// enQueue(Q,e->lchild);
// enQueue(Q,e->rchild);
// }
// while(!isEmptyQueue)
// {
// BNode *e = NULL;
// deQueue(Q,&e);
// if(e != NULL)
// {
// return 0;
// }
// }
// return 1;
//}
/*
队列
*/
#define MAX_SIZE 100
typedef struct QElemType
{
int level;
BNode *pNode;
}QElemType;
typedef struct Queue
{ //该指针用于指向存储二叉树中每个结点地址的数组,该数组中的每个元素是一个地址
QElemType *pList;
int front; //列头
int rear; //队尾,牺牲一个存储单元来表示队列满和空
}Queue;
//对队列进行初始化
void initQueue(Queue &Q)
{
//用pList指向一个用于存储结点地址的顺序表
Q.pList = (QElemType *) malloc(sizeof(QElemType) * MAX_SIZE);
//这个特殊的顺序表只能在rear存入数据,且rear永远指向下一个存储数据的空白单元
//front指向已经存储进去的元素,且front永远指向未来第一个要出队列的数据所在单元,
//队列为空时,front指向rear(空白数据单元)
Q.rear = 0; //当前队列为空,所以下一个存储内容的单元索引为零
Q.front = 0; //当前队列为空,约定rear = front = 0
}
void enQueue(Queue &Q, QElemType e)
{
//进队列时先应该判断是否满,插入的位置是在rear,
//入队列后,rear存储数据将要移到下一个位置pos,如果pos是front,则rear = front
//因为之前规定front = rear为队空,但是实际上队列是满的,为了解决这种矛盾,
//将(rear + 1) % MAX_SIZE = front视为队列满了,也就是不能再存入数据,牺牲掉一个空白单元
int nextInsrtPos = (Q.rear + 1) % MAX_SIZE;
//在rear当前指向的存储单元写入数据
Q.pList[Q.rear] = e;
Q.rear = nextInsrtPos; //移向下一个待写入数据的空白单元
}
void deQueue(Queue &Q, QElemType *e)
{
*e = Q.pList[Q.front];//取出元素内容
Q.front = (Q.front + 1) % MAX_SIZE; //往后移动一个位置
}
int isEmptyQueue(Queue Q)
{
if (Q.front == Q.rear)
return 1;
else
return 0;
}
/*
求一棵二叉树的最大宽度
*/
int getWidth(BiTree T)
{
if(T == NULL)//空树宽度为0
{
return 0;
}
Queue Q;//定义一个队列
initQueue(Q);//初始化一个队列
QElemType e;//定义结构体数组
e.pNode = T;
e.level = 1;
enQueue(Q,e);//将根结点压入队列
int curWidth = 0;//当前层数宽度
int maxWidth = 0;//最大宽度
int curLev = e.level;//当前层数
while(!isEmptyQueue(Q))//访问队列中的元素
{
deQueue(Q,&e);//出队列
if(e.level == curLev)
{
curWidth++;//累加一层中的所有结点
}
else
{
if(curWidth > maxWidth)//更新最大宽度
{
maxWidth = curWidth;
}
curLev = e.level;//更新当前层号
curWidth = 1;//更新当前宽度
}
//想想为什么不能放入if语句内---->当curLev != e.level时无法执行,就执行第二层第一个的时候无法将其左右孩子结点压入队列
//将左孩子及其层号压入队列
BNode *pLchi = e.pNode->lchild;
if(pLchi != NULL)
{
QElemType temp;
temp.pNode = pLchi;
temp.level = e.level + 1;
enQueue(Q,temp);
}
//将右孩子及其层号压入队列
BNode *pRchi = e.pNode->rchild;
if(pRchi != NULL)
{
QElemType temp;
temp.pNode = pRchi;
temp.level = e.level + 1;
enQueue(Q,temp);
}
}
if(curWidth > maxWidth)//更新最大宽度
{
maxWidth = curWidth;
}
return maxWidth;
}
int main()
{
char levelOrderList[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
int levelOrderListLength = 7;
char inOrderList[] = {'D', 'B', 'E', 'A', 'F', 'C', 'G'};
int inOrderListLength = 7;
BiTree T = createBiTree(levelOrderList, 0, levelOrderListLength - 1,
inOrderList, 0, inOrderListLength - 1);
char levelOrderList2[] = {'A', 'B', 'C', 'D', 'E', 'F', 'H'};
int levelOrderListLength2 = 7;
char inOrderList2[] = {'D', 'B', 'E', 'A', 'F', 'C', 'H'};
int inOrderListLength2 = 7;
BiTree T2 = createBiTree(levelOrderList2, 0, levelOrderListLength2 - 1,
inOrderList2, 0, inOrderListLength2 - 1);
char preArithmtic[] = {'*','+','1','2','3'};
char inArithmtic[] = {'1','+','2','*','3'};
int arithmticLenght = 5;
BiTree T3 = createBiTree(preArithmtic, 0, arithmticLenght - 1, inArithmtic, 0, arithmticLenght - 1);
preOrd(T);
printf("\n");
printf("结点个数: %d\n",getNodes(T));
printf("x结点: %c\n",getXNode(T,'D')->data);
printf("深度: %d\n",getHeight(T));
printf("x结点深度: %d\n",getXHeight(T,'D'));
swiLRChild(T);
printf("交换二叉树左右子树先序: ");
preOrd(T);
printf("\n");
printf("判断两颗树是否相似: %d\n",isSimilar(T,T2));
printf("叶子结点个数: %d\n",getLeafNode(T));
printf("双链表: ");
// operFunc(T);
printf("\n");
printf("表达式: %d\n",getValue(T3));
printf("层次遍历: ");
// levOrd(T);
printf("\n");
// printf("判断完全二叉树: %d\n",isComplete(T));
printf("最大宽度: %d\n",getWidth(T));
}
数据结构树递归
最新推荐文章于 2023-01-29 14:02:09 发布
![](https://img-home.csdnimg.cn/images/20240711042549.png)