二叉树的概念
二叉树是一种树形结构,其特点是每个结点至多只有两棵子树( 即二叉树中不存在度大于2的结点),并且二叉树的子树有左右之分,其次序不能任意颠倒。
二叉树的存储
顺序存储
即按照从上到下的顺序逐层存放,遇到为空的结点用‘0’表示。
链式存储
采用链式存储结构,用左指针域(lchild)存放结点的左孩子,用右指针域(rchild)存放右孩子
二叉树的创建
这是最常见的创建二叉树的方法。采用递归的形式,遇到空结点输入‘^’表示空。如果用户输入判断非空,则创建该结点,为它分配空间并且赋值。随后递归调用自身,以左节点为根继续判断。
typedef char DataType;
typedef struct Node
{
DataType data;
struct Node * Lchild;
struct Node * Rchild;
}BiTNode,*BiTree;
BiTree CreatBiTree()//用扩展先序遍历序列创建二叉链表
{
BiTree bt;
char ch;
ch=getchar();
if(ch=='^')
return NULL;
bt=(BiTree )malloc(sizeof(BiTNode));
bt->data=ch;
bt->Lchild = CreatBiTree();
bt->Rchild = CreatBiTree();
return bt;
}
比如用户输入:621^^43^^^8^^,其结果如图所示:
二叉树的遍历
二叉树的遍历有很多方法,例如递归的先序、中序、后序遍历,非递归遍历,按层次遍历等。
递归遍历
先序遍历
操作过程如下:
若二叉树为空,则什么也不做,否则,
1)访问根结点;
2)先序遍历左子树;
3)先序遍历右子树
中序遍历
操作过程如下:
若二叉树为空,则什么也不做,否则,
1)中序遍历左子树;
2)访问根结点;
3)中序遍历右子树。
后序遍历
操作过程如下:
若二叉树为空,则什么也不做,否则,
1)后序遍历左子树;
2)后序遍历右子树;
3)访问根结点。
例如此二叉树:
先序遍历的结果:6 2 1 4 3 8
中序遍历的结果:1 2 3 4 6 8
后序遍历的结果:1 3 4 2 8 6
代码实现
此代码是后序遍历代码,先序、中序只不过将printf函数调换顺序就可以实现。
//后序遍历
void HindOrderLayer (BiTree bt){
if(bt==NULL){
return;
}
HindOrderLayer(bt->Lchild);
HindOrderLayer(bt->Rchild);
printf("%d ",bt->data);
}
非递归遍历
任何能以递归形式处理的问题都能以非递归的栈来处理,二叉树的遍历也不例外。
此代码使用栈的思想,进行非递归的先序遍历。先判断此树是否为空,如果为空直接返回就行。
先将根节点入栈
stack[++top] = root;
然后在while循环中,依次取出栈顶元素并打印,然后将该结点的右孩子和左孩子依次进栈,因为我们进行的是先序遍历,根据栈的后进先出规则,左孩子后进的,则会先被弹出栈。
当栈为空的时候则遍历结束。
代码实现:
void preorderTraversal(BiTree root) {
if (root == NULL) {
return;
}
BiTree stack[1000];
int top = -1;
stack[++top] = root;//入栈
while (top >= 0) {
BiTree node = stack[top--];//出栈
printf("%d ", node->data);
if (node->Rchild) {
stack[++top] = node->Rchild;
}
if (node->Lchild) {
stack[++top] = node->Lchild;
}
}
}
按层次遍历
按层次遍历即从上到下从左到右依次遍历。此方法要用到的是队列的操作。
还是以这个树为例:
先将根结点入队,此时队列中有‘6’;
然后将根结点出队打印,并将根结点的左孩子右孩子入队,此时队列中有‘2’,‘8’;
然后继续将‘2’出队打印,并将‘2’的左孩子右孩子入队,此时队列中有‘8’,‘1’,‘4’;
就这样继续操作直到队列为空,此时打印出来的就是按层次遍历的结果。
代码实现
void levelOrderTraversal(BiTree root) {
if (root == NULL) {
return;
}
struct Node* queue[1000];
int front = 0;
int rear = 0;
queue[rear++] = root;
while (front < rear) {
struct Node* node = queue[front++];
printf("%d ", node->data);
if (node->Lchild) {
queue[rear++] = node->Lchild;
}
if (node->Rchild) {
queue[rear++] = node->Rchild;
}
}
}
完整代码
#include<stdio.h>
#include<stdlib.h>
typedef char DataType;
typedef struct Node
{
DataType data;
struct Node * Lchild;
struct Node * Rchild;
}BiTNode,*BiTree;
void preorderTraversal(BiTree root);
void HindOrderLayer (BiTree bt);
BiTree CreatBiTree();//用扩展先序遍历序列创建二叉链表
void levelOrderTraversal(BiTree root);
int main()
{
BiTree root;
root=CreatBiTree();
printf("后序遍历\n");
HindOrderLayer (root);
printf("\n非递归遍历\n");
preorderTraversal(root);
printf("\n按层次遍历遍历\n");
levelOrderTraversal(root);
}
BiTree CreatBiTree()//用扩展先序遍历序列创建二叉链表
{
BiTree bt;
char ch;
ch=getchar();
if(ch=='^')
return NULL;
bt=(BiTree )malloc(sizeof(BiTNode));
bt->data=ch;
bt->Lchild = CreatBiTree();
bt->Rchild = CreatBiTree();
return bt;
}
void levelOrderTraversal(BiTree root) {
if (root == NULL) {
return;
}
struct Node* queue[1000];
int front = 0;
int rear = 0;
queue[rear++] = root;
while (front < rear) {
struct Node* node = queue[front++];
printf("%d ", node->data);
if (node->Lchild) {
queue[rear++] = node->Lchild;
}
if (node->Rchild) {
queue[rear++] = node->Rchild;
}
}
}
void HindOrderLayer (BiTree bt){
if(bt==NULL){
return;
}
HindOrderLayer(bt->Lchild);
HindOrderLayer(bt->Rchild);
printf("%d ",bt->data);
}
void preorderTraversal(BiTree root) {
if (root == NULL) {
return;
}
BiTree stack[1000];
int top = -1;
stack[++top] = root;
while (top >= 0) {
BiTree node = stack[top--];
printf("%d ", node->data);
if (node->Rchild) {
stack[++top] = node->Rchild;
}
if (node->Lchild) {
stack[++top] = node->Lchild;
}
}
}