数据结构-二叉树的非层次遍历以及应用(输出叶子结点,求树的高度)
树的定义
以树节点的堆栈和队列的结构
堆栈的操作
前序,中序,和后序的非递归遍历
使用堆栈可以对二叉树进行层次遍历
输出树的叶子结点
求树的高度
树的定义:
typedef struct TreeNode* BinTree;
typedef BinTree Position;//BinTNode
struct TreeNode {//BinTNode
ElemType Data;
BinTree Left;
BinTree Right;
};
以树节点的堆栈和队列的结构
这里用数组表示了,也可以使用链表存储。
typedef struct SqStack
{
TreeNode* data[MAX_TREE_SIZE];
int top;
}SqStack, * Stack;
typedef struct
{
TreeNode* Data[MAX_TREE_SIZE];
int rear;
int front;
}Queue, * SQueue;
堆栈的操作:
/*判断是否为空栈*/
Status IsEmpty(Stack S)
{
if (S->top == -1)
return OK;
else
return False;
}
//返回栈顶元素
BinTree getTop(SqStack* S)
{
if (S->top == -1)
{
printf("表是空的\n");
exit(0);
}
return (S->data[S->top]);
}
//压栈
BinTree Push(SqStack* S, BinTree T)
{/*top=-1为栈低*/
if (S->top == MAX_TREE_SIZE - 1)
{
printf("表已经满了!");
exit(0);
}
S->top++;
S->data[S->top] = T;
}
/*POP,出栈*/
BinTree Pop(SqStack* S)
{
if (S->top == -1)
{
printf("表是空的\n");
exit(0);
}
return (S->data[S->top--]);
}
前序,中序,和后序的非递归遍历
使用堆栈可以实现二叉树的非递归遍历,下面就是前序,中序,和后序的非递归遍历。.
/*中序遍历*/
void InOrderTraversals(BinTree BT)
{
BinTree T = BT;
Stack S;/*创建并初始化堆栈*/
while (T || !IsEmpty(S))//
{/*一直向左并将沿途结点压入堆栈*/
while (T)
{
Push(S, T);
T = T->Left;
}//出来的条件是要改变方向了,也就是说访问完了最左边的结点。
if (!IsEmpty(S))
{
T = Pop(S);/*访问结点*/
printf("%d", T->Data);
T = T->Right;//转向右子树
}
}
}
/*先序,后序*/
void PreOrderTraversals(BinTree BT)
{
BinTree T = BT;
Stack S ;/*创建并初始化堆栈*/
while (T || !IsEmpty(S))
{/*一直向左并将沿途结点压入堆栈*/
while (T)
{
printf("%d", T->Data);
Push(S, T);
T = T->Left;
}
if (!IsEmpty(S))//获取栈顶元素,转向其右子树
{
T = Pop(S);/*访问结点*/
T = T->Right;//转向右子树
}
}
}
void PostOrderTraversals(BinTree BT)
{
BinTree Pre, T;//pre用于存放上一个访问过的结点,T用于存放当前的结点
T = BT;//用于将新发现的结点压站
Pre = NULL;
Stack S;
while (T || IsEmpty(S))
{
while (T)
{
Push(S, T);
T = T->Left;
}
//while结束是因为找到了最低左端结点
BinTree top = getTop(S);
if (top->Right == NULL || top->Right == Pre)
{//如果又结点为空,或者右孩子已经被访问过来,就要访问该结点
printf("%d", top->Data);
Pop(S);
Pre = top;
}
else
{
T = top->Right;
}
}
}
队列的操作
队列的出队、入队操作
/*队列*/
Status AddQ(SQueue Q, BinTree T)
{
if ((Q->rear + 1) % MAX_TREE_SIZE == Q->front)
exit(0);
Q->Data[Q->rear] = T;
Q->rear = (Q->rear + 1) % MAX_TREE_SIZE;
return OK;
}
BinTree DeleteQ(SQueue Q)
{
if (Q->rear == Q->front)
exit(0);
return Q->Data[Q->front++];
}
使用堆栈可以对二叉树进行层次遍历
层次遍历的思想就是,一层一层的进行遍历。也就是说,先遇到根结点,让它入队,然后进行循还:出队、访问、左右儿子入队。
void LevelOrderTraversal(BinTree BT)
{
SQueue Q;
BinTree T;
if (!BT) return;
InitQueue(Q);
AddQ(Q, BT);
while (Q->front != Q->rear)
{
T = DeleteQ(Q);
printf("%d\n", T->Data);
if (T->Left)
AddQ(Q, T->Left);
if (T->Right)
T->Right);
}
}
输出树的叶子结点
思路: 叶子结点就是左右孩子都为空的结点,所以可以在递归前序遍历的基础上 解决这个问题
void PreOrderPrintLeaves(BinTree BT)
{
if (BT)/*判断是否为空树*/
{
if (!BT->Left && !BT->Right)
printf("%d", BT->Data);/*如果是叶子结点就将它访问输出*/
PreOrderPrintLeaves(BT->Left);//递归访问左子树
PreOrderPrintLeaves(BT->Right);//递归访问右子树
}
}
求树的高度
思路:拿到一个结点,就去遍历左右子树,如果没有左子树,就去找右子树, 一直找到最后一个结点,采用后序遍历的做法,当然前序后序中序没啥区别
int PostOrderGetHeight(BinTree BT)
{
int HL, HR, MaxH;
if (BT)
{
HL = PostOrderGetHeight(BT->Left);//求左子树的高度
HR = PostOrderGetHeight(BT->Right);//求右子树的高度
MaxH = (HL > HR) ? HL : HR;
return MaxH + 1;//返回树的高度.
}
else
return 0;
}