综述:
本题前中后序遍历二叉树都很简单,层序遍历就没那么容易了,我开始是用队列实现的层序遍历,但是不知道为什么在PTA上跑不过,但是在VS上我测试程序是没有问题的,可能是编译器的原因,在PTA上我只能用另一个方法实现层序的遍历,在本文中,将讲述队列实现层序遍历以及在PTA上跑过的另外一种方法遍历,其实两种方法的思想还是挺相像的。并且我在最后会贴上VS的测试用例。
目录
题目:
本题要求给定二叉树的4种遍历。
函数接口定义:
void InorderTraversal( BinTree BT );
void PreorderTraversal( BinTree BT );
void PostorderTraversal( BinTree BT );
void LevelorderTraversal( BinTree BT );
其中BinTree
结构定义如下:
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree Left;
BinTree Right;
};
要求4个函数分别按照访问顺序打印出结点的内容,格式为一个空格跟着一个字符。
裁判测试程序样例:
#include <stdio.h>
#include <stdlib.h>
typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
ElementType Data;
BinTree Left;
BinTree Right;
};
BinTree CreatBinTree(); /* 实现细节忽略 */
void InorderTraversal( BinTree BT );
void PreorderTraversal( BinTree BT );
void PostorderTraversal( BinTree BT );
void LevelorderTraversal( BinTree BT );
int main()
{
BinTree BT = CreatBinTree();
printf("Inorder:"); InorderTraversal(BT); printf("\n");
printf("Preorder:"); PreorderTraversal(BT); printf("\n");
printf("Postorder:"); PostorderTraversal(BT); printf("\n");
printf("Levelorder:"); LevelorderTraversal(BT); printf("\n");
return 0;
}
/* 你的代码将被嵌在这里 */
输出样例(对于图中给出的树):
Inorder: D B E F A G H C I
Preorder: A B D F E C G H I
Postorder: D E F B H G I C A
Levelorder: A B C D F G I E H
函数接口1-中序遍历:
二叉树的前中后序遍历原理一样,函数实现也基本一样,只是顺序有所不同,思想是递归的思想,如中序为:左子树、根、右子树,其中左子树右子树又可以做根遍历下面的左子树、根、右子树。具体实现可以看下面的函数递归展开图。(这棵二叉树还是有点大,我只画完了整棵左树)
中序遍历代码:
void InorderTraversal(BinTree BT)
{
if (BT == NULL)
{
return;
}
InorderTraversal(BT->left);
printf(" %c", BT->data);
InorderTraversal(BT->right);
}
函数接口2-前序遍历:
前序遍历代码:
void PreorderTraversal(BinTree BT)
{
if (BT == NULL)
{
return;
}
printf(" %c", BT->data);
PreorderTraversal(BT->left);
PreorderTraversal(BT->right);
}
函数接口3-后序遍历:
后序遍历代码:
void PostorderTraversal(BinTree BT)
{
if (BT == NULL)
{
return;
}
PostorderTraversal(BT->left);
PostorderTraversal(BT->right);
printf(" %c", BT->data);
}
函数接口4-层序遍历:
层序遍历不是很容易,怎么才能实现一层一层的遍历呢?先遍历根再左子树、右子树、左子树的左子树、左子树的右子树,右子树的左子树、右子树的右子树........这样一层层的下去~
1、数组&指针实现:
具体思路为创立一个指针数组,数组里的元素都是指向二叉树节点的指针。用一个变量last控制二叉树的节点一个一个的往数组里面存储,用另一个变量prev控制打印数据,
实现代码:
void LevelorderTraversal( BinTree BT )
{
if(BT==NULL)
{
return;
}
BinTree q[1000],p;
int prev=0,last=0;
q[last++]=BT;
while(prev!=last)
{
p=q[prev++];
printf(" %c",p->Data);
if(p->Left!=NULL)
{
q[last++]=p->Left;
}
if(p->Right!=NULL)
{
q[last++]=p->Right;
}
}
}
2、队列实现:
层序遍历这棵二叉树正确顺序为ABCDFGIEH,队列性质先进先出,只要依次入队依次Pop打印就很容易实现~具体实现如下图
实现代码:(VS测试)
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef char ElementType;
typedef struct TNode* Position;
typedef Position BinTree;
struct TNode {
ElementType data;
BinTree left;
BinTree right;
};
//BinTree CreatBinTree(); /* 实现细节忽略 */
void InorderTraversal(BinTree BT);
void PreorderTraversal(BinTree BT);
void PostorderTraversal(BinTree BT);
void LevelorderTraversal(BinTree BT);
int main()
{
// BinTree BT = CreatBinTree();
BinTree A = (BinTree)malloc(sizeof(struct TNode));
A->data = 'A';
A->left = NULL;
A->right = NULL;
BinTree B = (BinTree)malloc(sizeof(struct TNode));
B->data = 'B';
B->left = NULL;
B->right = NULL;
BinTree C = (BinTree)malloc(sizeof(struct TNode));
C->data = 'C';
C->left = NULL;
C->right = NULL;
BinTree D = (BinTree)malloc(sizeof(struct TNode));
D->data = 'D';
D->left = NULL;
D->right = NULL;
BinTree E = (BinTree)malloc(sizeof(struct TNode));
E->data = 'E';
E->left = NULL;
E->right = NULL;
A->left = B;
A->right = C;
B->left = D;
B->right = E;
printf("Inorder:"); InorderTraversal(A); printf("\n");
printf("Preorder:"); PreorderTraversal(A); printf("\n");
printf("Postorder:"); PostorderTraversal(A); printf("\n");
printf("Levelorder:"); LevelorderTraversal(A); printf("\n");
return 0;
}
/* 你的代码将被嵌在这里 */
typedef BinTree QDataType;
typedef struct QueueNode
{
struct QueueNode* next;
QDataType data;
}QNode;
typedef struct Queue
{
QNode* head;
QNode* tail;
}Queue;
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = pq->tail = NULL;
}
void QueueDestory(Queue* pq)
{
assert(pq);
QNode* cur = pq->head;
while (cur)
{
QNode* next = cur->next;
free(cur);
cur = next;
}
pq->head = pq->tail = NULL;
}
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
printf("malloc fail\n");
exit(-1);
}
newnode->data = x;
newnode->next = NULL;
if (pq->tail == NULL)
{
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = newnode;
}
}
void QueuePop(Queue* pq)
{
assert(pq);
assert(pq->head);
if (pq->head->next == NULL)
{
free(pq->head);
pq->head = pq->tail = NULL;
}
else
{
QNode* next = pq->head->next;
free(pq->head);
pq->head = next;
}
}
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(pq->head);
return pq->head->data;
}
QDataType QueueBack(Queue* pq)
{
assert(pq);
assert(pq->head);
return pq->tail->data;
}
int QueueEmpty(Queue* pq)
{
assert(pq);
if (pq->head == NULL)
{
return 1;
}
else
{
return 0;
}
}
void InorderTraversal(BinTree BT)
{
if (BT == NULL)
{
return;
}
InorderTraversal(BT->left);
printf("%c ", BT->data);
InorderTraversal(BT->right);
}
void PreorderTraversal(BinTree BT)
{
if (BT == NULL)
{
return;
}
printf("%c ", BT->data);
PreorderTraversal(BT->left);
PreorderTraversal(BT->right);
}
void PostorderTraversal(BinTree BT)
{
if (BT == NULL)
{
return;
}
PostorderTraversal(BT->left);
PostorderTraversal(BT->right);
printf("%c ", BT->data);
}
void LevelorderTraversal(BinTree BT)
{
Queue q;
QueueInit(&q);
if (BT)
QueuePush(&q, BT);
while (!QueueEmpty(&q))
{
BinTree front = QueueFront(&q);
QueuePop(&q);
printf("%c ", front->data);
if (front->left)
{
QueuePush(&q, front->left);
}
if (front->right)
{
QueuePush(&q, front->right);
}
}
QueueDestory(&q);
}
总结:
仔细想想,通过数组或者是队列实现层序遍历,这两种方法特别相像,只不过队列打印完一个节点的数据直接把该节点删除了,而数组并没有,只是一个个的遍历~
附:层序遍历和递归展开图太多了,难画的一批~基本功不够还要画就让人头大哦。