递归
1.先序遍历(根左右)
void BinaryTreePrevOrder(BTNode* root) //先序遍历 根左右 (递归)
{
if (root)
{
putchar(root->data);//打印根节点
BinaryTreePrevOrder(root->lchild);
BinaryTreePrevOrder(root->rchild);
}
}
2.中序遍历 (左根右)
void BinaryTreeInOrder(BTNode* root) //中序遍历 左根右 (递归)
{
if (root)
{
BinaryTreeInOrder(root->lchild);
putchar(root->data);
BinaryTreeInOrder(root->rchild);
}
}
3.后序遍历(左右根)
void BinaryTreePostOrder(BTNode* root)//后序遍历 左右根 (递归)
{
if (root)
{
BinaryTreePostOrder(root->lchild);
BinaryTreePostOrder(root->rchild);
putchar(root->data);
}
}
非递归(需要用到栈来实现)
需要用到的栈的代码
void StackInit(Stack* psl, size_t capicity)
{
assert(psl);
psl->capicity = capicity;
psl->array = (SLDataType *)malloc(capicity * sizeof(SLDataType));
assert(psl->array);
psl->size = 0;
}
void StackDestory(Stack* psl)
{
assert(psl);
if (psl->array)
{
free(psl->array);
psl->array = NULL;
psl->size = 0;
psl->capicity = 0;
}
}
void CheckCapacity(Stack* psl)
{
assert(psl);
if (psl->size == psl->capicity)
{
psl->capicity *= 2;
psl->array = (SLDataType *)realloc(psl->array, psl->capicity * sizeof(SLDataType));
}
}
void StackPush(Stack* psl, SLDataType x)
{
assert(psl);
CheckCapacity(psl);
psl->array[psl->size] = x;
psl->size++;
}
void StackPop(Stack* psl)
{
assert(psl || psl->size);
psl->size--;
}
SLDataType StackTop(Stack* psl)
{
if (StackIsEmpty(psl))
{
return (SLDataType)0;
}
return psl->array[psl->size - 1];
}
int StackIsEmpty(Stack * psl)
{
return psl->size == 0;
}
1.先序遍历
(1)、打印当前节点
(2)、如果它有右孩子就将齐入栈
(3)、如果它有左孩子就访问左孩子,如果没有,就访问栈顶。
void BinaryTreePrevOrderNonR(BTNode* root) // 先序遍历 (非递归)
{
Stack st;
BTNode * cur = root;
StackInit(&st, 100); //初始化栈
while (cur)
{
putchar(cur->data); //打印当前根节点的值
if (cur->rchild) //右孩子存在
{
StackPush(&st, cur->rchild); //右孩子入栈
}
if (cur->lchild) //左孩子存在
{
cur = cur->lchild; //根节点为左孩子
}
else//没有左孩子取栈顶
{
cur = StackTop(&st); //取到空时,遍历结束
StackPop(&st); //出栈
}
}
StackDestory(&st);
}
2.中序遍历
(1)、从当前节点开始遍历左子树,将所有的节点入栈,直到左子树为空
(2)、取出并打印栈顶,访问它的右孩子,如果右孩子,重复过程1,如果没有右孩子,重复过程2
void BinaryTreeInOrderNonR(BTNode* root) //中序遍历 (非递归)
{
Stack st;
BTNode* cur = root;
StackInit(&st,100);
while (cur || !StackIsEmpty(&st))//(1)
{
for (; cur; cur = cur->lchild)//将当前节点及左孩子入栈 (链表遍历)
{
StackPush(&st, cur);
}
cur = StackTop(&st);//取出栈顶 (1、右孩子为空,for循环不进直接取栈顶。
//2、如果右孩子不为空,那么这是一个没有左孩子的节点。
//第一种情况是左子树访问完毕,第二种情况是右子树为空。
//无论哪种,当前节点都要打印。)
/*if (!cur )
{
break;
}*/
putchar(cur->data);
StackPop(&st);
cur = cur->rchild;
}
StackDestory(&st);
}
3.后序遍历
LT = 左子树访问标记,即代码中tag数组
(1)、从当前节点开始遍历左子树,将所有节点入栈,且清空LT标记,直到左子树为空,然后就进入过程2
(2)、访问栈顶,置位它的LT标记,访问它的右子树,如果右子树存在,重复过程1,如果右子树不存在,进入过程3
(3)、取出栈顶,打印,然后检测它的父节点的LT是否也被置位,如果是,则一并打印,直到找到第一个LT标记为清空状态的节点位置,然后返回到过程2
void BinaryTreePostOrderNonR(BTNode* root)//后序遍历 (非递归)
{
char tag[64];
Stack st;
BTNode* cur = root;
StackInit(&st, 100);
do
{
for (; cur; cur = cur->lchild)//将当前节点及左孩子入栈 (链表遍历)
{
StackPush(&st, cur);//左孩子入栈
tag[st.size - 1] = 0;//重置左子树访问标记(LT)
}
while (!StackIsEmpty(&st)&&tag[st.size - 1])//栈不为空并且标记为1
//前面的条件只在最后一次循环跳出时生效
//后面的条件分两种情况
//1、当cur为空时,上面的for不进,此条件成立。
//2、当cur不为空,上面的for进,此条件不成立。
//如果检测到当前的LT被置位,那么在打印完当前节点后,再去直接检查上一个节点(父节点)也要被打印了
{
cur = StackTop(&st); //取栈顶
putchar(cur->data);//打印
StackPop(&st);//出栈
}
if (!StackIsEmpty(&st))//栈不为空 //此条件只在最后一次循环跳出时生效
{
cur = StackTop(&st);//取栈顶
//1、如果上面的while进了,那么证明左子树访问完毕,给LT置位
//2、如果上面的while没进,那么证明左子树不存在,给LT置位
tag[st.size - 1] = 1;//标记改为1
cur = cur->rchild; //取右孩子
//左子树访问完毕后,访问右子树
}
//
} while (!StackIsEmpty(&st));//由于后序遍历中根节点最后出栈前,栈不可能为空,所以以根节点是否为空判断
StackDestory(&st);
}
4.层序遍历 (需要队列的辅助来实现)
有关队列的代码
void QueueInit(Queue* plist)
{
assert(plist);
plist->_head = NULL;
plist->_rear = NULL;
}
void QueueDestory(Queue* plist)
{
QueueNode * tmp;
while (plist->_head)
{
tmp = plist->_head;
plist->_head = plist->_head->_next;
free(tmp);
}
}
void QueuePop(Queue* plist)
{
assert(plist);
QueueNode * tmp;
if (plist->_head)
{
tmp = plist->_head;
plist->_head = plist->_head->_next;
free(tmp);
}
}
void QueuePush(Queue* plist, QuDataType x)
{
QueueNode * cur = (QueueNode *)malloc(sizeof(QueueNode));
cur->_data = x;
cur->_next = NULL;
if (QueueIsEmpty(plist))
{
plist->_head = plist->_rear = cur;
return;
}
plist->_rear->_next = cur;
plist->_rear = cur;
}
int QueueIsEmpty(Queue * plist)
{
return plist->_head == NULL;
}
QuDataType QueueTop(Queue *plist)
{
if (QueueIsEmpty(plist))
{
return (QuDataType)0;
}
return plist->_head->_data;
}
层序遍历的实现
先将根入列
(1)、取队顶打印
(2)、如果它有左孩子就入队左孩子,如果它有右孩子就入队右孩子
(3)、队顶出队
void BinaryTreeLeveorder(BTNode* root)//层序遍历
{
Queue qu;
BTNode * cur;
QueueInit(&qu);//初始化队列
QueuePush(&qu, root);//入队列
while (!QueueIsEmpty(&qu))//队列不为空
{
cur = QueueTop(&qu); //cur 等于队列头
putchar(cur->data); //输出cur
if (cur->lchild) // 左孩子存在
{
QueuePush(&qu, cur->lchild);//左孩子入队列
}
if (cur->rchild)//右孩子存在
{
QueuePush(&qu, cur->rchild); //右孩子入队列
}
QueuePop(&qu);//队头元素出队列
}
QueueDestory(&qu);//销毁
}