(一)顺序结构创建二叉树
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 100 //存储空间初始分配量
#define MAX_TREE_SIZE 100 //二叉树的最大结点数
typedef char TElemType;
typedef int Status;
typedef TElemType SqBiTree[MAX_TREE_SIZE]; //定义顺序二叉树的结构
typedef struct
{
int level, order; //结点的层,本层的序号
}Position;
TElemType Nil = '^'; //设置结点以^为空
Status InitBiTree(SqBiTree T); //构造空二叉树T,因为T是固定数组,不会改变,故不需要&
Status CreateBiTree(SqBiTree T);//按照层序次序输入二叉树中结点的值,构造顺序存储的二叉树
Status BiTreeEmpty(SqBiTree T);//判断二叉树是否为空
int BiTreeDepth(SqBiTree T);//获取二叉树的深度
Status Root(SqBiTree T, TElemType* e);//返回根节点数据
TElemType Value(SqBiTree T, Position e);//获取具体位置的结点值
Status Assign(SqBiTree T, Position e, TElemType value);//对某个叶子结点赋值
TElemType Parent(SqBiTree T, TElemType e);//根据元素,获取其双亲结点的值
TElemType LeftChild(SqBiTree T, TElemType e);//返回结点的左孩子
TElemType RightChild(SqBiTree T, TElemType e);//返回结点的右孩子
TElemType LeftSibling(SqBiTree T, TElemType e);//返回结点的左兄弟
TElemType RightSibling(SqBiTree T, TElemType e);//返回结点的右兄弟
void PreOrderTraverse(SqBiTree T, int e);//开始进行前序遍历
void InOrderTraverse(SqBiTree T, int e);//开始进行中序遍历
void PostOrderTraverse(SqBiTree T, int e);//开始进行后序遍历
void LevelOrderTraverse(SqBiTree T);//开始进行层序遍历
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 100 //存储空间初始分配量
#define MAX_TREE_SIZE 100 //二叉树的最大结点数
typedef char TElemType;
typedef int Status;
typedef TElemType SqBiTree[MAX_TREE_SIZE]; //定义顺序二叉树的结构
typedef struct
{
int level, order; //结点的层,本层的序号
}Position;
TElemType Nil = '^'; //设置结点以^为空
//构造空二叉树T,因为T是固定数组,不会改变,故不需要&
Status InitBiTree(SqBiTree T)
{
int i;
for (i = 0; i < MAX_TREE_SIZE; i++)
T[i] = Nil;
return OK;
}
//按照层序次序输入二叉树中结点的值,构造顺序存储的二叉树T
Status CreateBiTree(SqBiTree T)
{
int i = 0;
char ch;
printf("please enter value for node(^ is Nil,# exit) number must <= %d:
",MAX_TREE_SIZE);
scanf("%c", &ch);
while (ch!='#')
{
T[i++] = ch;
if (i != 0 && T[i] != Nil &&T[(i + 1) / 2 - 1] == Nil) //不为根节点,自己又不为空,父节点又不存在,一定是错的
{
printf("exist a node not parents node:%c",T[i]);
exit(ERROR);
}
scanf("%c", &ch);
}
//将后面的结点全部置为空:是为了防止使用时创建两次二叉树,出现数据冗余
while (i<MAX_TREE_SIZE)
{
T[i++] = Nil; //将空值赋给T后面的结点
}
return OK;
}
#define ClearBiTree InitBiTree //在顺序存储结构中,两者是一致的
//判断二叉树是否为空
Status BiTreeEmpty(SqBiTree T)
{
if (T[0] == Nil)
return TRUE;
return FALSE;
}
//获取二叉树的深度
int BiTreeDepth(SqBiTree T)
{
int i, j=-1;
for (i = MAX_TREE_SIZE-1; i >= 0; i--) //获取最后一个结点
if (T[i] != Nil)
break;
//根据pow判断深度
i++; //获取从1开始的二叉树,而不是以0开始,方便下面计算
do
{
j++;
} while (i>=pow(2,j));
return j;
}
//返回根节点数据
Status Root(SqBiTree T, TElemType* e)
{
if (BiTreeEmpty(T))
return ERROR;
*e = T[0];
return OK;
}
//获取具体位置的结点值
TElemType Value(SqBiTree T, Position e)
{
return T[(int)pow(2,e.level-1)-2+e.order];
}
//对某个叶子结点赋值
Status Assign(SqBiTree T, Position e, TElemType value)
{
//先将e转换Wie一维数组的下标
int index = (int)pow(2, e.level - 1) - 2 + e.order;
//判断其双亲是否存在
if (index != 0 && T[(index + 1) / 2 - 1] == Nil)
return ERROR;
//若是我们赋值为空,但是其子节点存在,也返回空
if (value == Nil && (T[index * 2 + 1] != Nil || T[index * 2 + 2] != Nil))
return ERROR;
T[index] = value;
return OK;
}
//根据元素,获取其双亲结点的值
TElemType Parent(SqBiTree T, TElemType e)
{
int i;
//若是空树
if (T[0] == Nil)
return Nil;
for (i = 1; i < MAX_TREE_SIZE; i++) //注意这里从1开始,若是出现在头结点,会直接在下面返回Nil
if (T[i] == e) //找到该结点
return T[(i + 1) / 2 - 1];
return Nil;
}
//返回结点的左孩子
TElemType LeftChild(SqBiTree T, TElemType e)
{
int i;
//若是空树
if (T[0] == Nil)
return Nil;
for (i = 1; i < MAX_TREE_SIZE; i++) //注意这里从1开始,若是出现在头结点,会直接在下面返回Nil
if (T[i] == e) //找到该结点
return T[2*i+1];
return Nil;
}
//返回结点的右孩子
TElemType RightChild(SqBiTree T, TElemType e)
{
int i;
//若是空树
if (T[0] == Nil)
return Nil;
for (i = 1; i < MAX_TREE_SIZE; i++) //注意这里从1开始,若是出现在头结点,会直接在下面返回Nil
if (T[i] == e) //找到该结点
return T[2 * i + 2];
return Nil;
}
//返回结点的左兄弟
TElemType LeftSibling(SqBiTree T, TElemType e)
{
int i;
//若是空树
if (T[0] == Nil)
return Nil;
for (i = 1; i < MAX_TREE_SIZE; i++) //注意这里从1开始,若是出现在头结点,会直接在下面返回Nil
if (T[i] == e&&i%2==0) //找到右节点
return T[i-1];
return Nil;
}
//返回结点的右兄弟
TElemType RightSibling(SqBiTree T, TElemType e)
{
int i;
//若是空树
if (T[0] == Nil)
return Nil;
for (i = 1; i < MAX_TREE_SIZE; i++) //注意这里从1开始,若是出现在头结点,会直接在下面返回Nil
if (T[i] == e&&i % 2 == 1) //找到左节点
return T[i + 1];
return Nil;
}
//开始进行前序遍历
void PreOrderTraverse(SqBiTree T,int e)
{
if (T&&e<MAX_TREE_SIZE)
{
if (T[e] != Nil)
printf("%c", T[e]);
PreOrderTraverse(T, 2 * e + 1);
PreOrderTraverse(T, 2 * e + 2);
}
}
//开始进行中序遍历
void InOrderTraverse(SqBiTree T, int e)
{
if (T&&e<MAX_TREE_SIZE)
{
InOrderTraverse(T, 2 * e + 1);
if (T[e] != Nil)
printf("%c", T[e]);
InOrderTraverse(T, 2 * e + 2);
}
}
//开始进行后序遍历
void PostOrderTraverse(SqBiTree T, int e)
{
if (T&&e<MAX_TREE_SIZE)
{
PostOrderTraverse(T, 2 * e + 1);
PostOrderTraverse(T, 2 * e + 2);
if (T[e]!=Nil)
printf("%c", T[e]);
}
}
//开始进行层序遍历
void LevelOrderTraverse(SqBiTree T)
{
int i = MAX_TREE_SIZE - 1;
int j;
while (T[i] == Nil)
i--;
for (j = 0; j <= i; j++)
if (T[j] != Nil)
printf("%c", T[j]); //值获取非空数据
}
函数实现代码
int main()
{
TElemType e;
Status i;
Position p;
SqBiTree T;
printf("1.InitBiTree
");
InitBiTree(T);
printf("2.CreateBiTree
");
CreateBiTree(T);
printf("3.LevelOrderTraverse
");
LevelOrderTraverse(T);
printf("
");
printf("4.PreOrderTraverse
");
PreOrderTraverse(T,0);
printf("
");
printf("5.InOrderTraverse
");
InOrderTraverse(T,0);
printf("
");
printf("6.PostOrderTraverse
");
PostOrderTraverse(T, 0);
printf("
");
printf("7.PostOrderTraverse
");
if (Root(T, &e))
printf("8.Root:%d
", e);
printf("9.PostOrderTraverse
");
printf("10.LeftChild for D --> %c
", LeftChild(T, 'D'));
printf("11.RightChild for D --> %c
", RightChild(T, 'D'));
printf("12.LeftSibling for H --> %c
", LeftSibling(T, 'H'));
printf("13.RightSibling for G --> %c
", RightSibling(T, 'G'));
printf("14.BiTreeDepth:%d
", BiTreeDepth(T));
p.level = 4;
p.order = 2;
printf("15.Value row4 col2:Z
");
Assign(T, p, 'Z');
LevelOrderTraverse(T);
system("pause");
return 0;
}
main函数测试
(二)链式结构创建二叉树
//按照前序输入二叉树中结点的值(一个字符)
//#表示空树,构造二叉树表表示二叉树T
void CreateBiTree(BiTree *T)
{
TElemType ch;
scanf("%c", &ch);
if (ch == '#')
*T = NULL;
else
{
*T = (BiTree)malloc(sizeof(BiTNode));
if (!*T)
exit(ERROR);
(*T)->data = ch; //生成根节点数据
CreateBiTree(&(*T)->lchild); //构造左子树
CreateBiTree(&(*T)->rchild); //构造右子树
}
}
(三)使用递归实现对二叉树的遍历
#include <stdio.h>
#include <stdlib.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#ifndef BINTREE_H
#define BINTREE_H
typedef char TElemType;
typedef int Status;
//二叉树的二叉链表结点结构定义
typedef struct BiTNode //结点结构
{
TElemType data; //结点数据
struct BiTNode *lchild, *rchild; //左右孩子指针
}BiTNode, *BiTree;
#endif
BinT.h
#define _CRT_SECURE_NO_WARNINGS
#include "BinT.h"
void PreOrderTraverse(BiTree T, int level)
{
if (T)
{
printf("%c in level %d
", T->data,level + 1);
PreOrderTraverse(T->lchild, level + 1);
PreOrderTraverse(T->rchild, level + 1);
}
}
void InOrderTraverse(BiTree T, int level)
{
if (T)
{
InOrderTraverse(T->lchild, level + 1);
printf("%c in level %d
", T->data, level + 1);
InOrderTraverse(T->rchild, level + 1);
}
}
void PostOrderTraverse(BiTree T, int level)
{
if (T)
{
PostOrderTraverse(T->lchild, level + 1);
PostOrderTraverse(T->rchild, level + 1);
printf("%c in level %d
", T->data, level + 1);
}
}
int main()
{
BiTree T;
printf("1.CreateBiTree
");
CreateBiTree(&T);
printf("2.PreOrderTraverse
");
PreOrderTraverse(T, 0);
printf("3.InOrderTraverse
");
InOrderTraverse(T, 0);
printf("4.PostOrderTraverse
");
PostOrderTraverse(T, 0);
system("pause");
return 0;
}
(四).使用栈实现非递归,遍历二叉树
#include <stdio.h>
#include <stdlib.h>
#include "BinT.h"
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 100
typedef BiTree ElemType;
typedef struct
{
ElemType data[MAXSIZE];
int top;
}sqStack;
Status InitStack(sqStack *s); //初始化操作,建立一个空栈
Status ClearStack(sqStack *s); //将栈清空
Status StackEmpty(sqStack s); //若栈存在,返回true,否则返回false
Status Push(sqStack *s, ElemType e); // 若是栈存在,则插入新的元素e到栈S中并成为栈顶元素
Status Pop(sqStack *s, ElemType *e); //若是栈存在且非空,删除栈顶元素,并用e返回其值
stack.h
#define _CRT_SECURE_NO_WARNINGS
#include "stack.h"
//初始化操作,建立一个空栈
Status InitStack(sqStack *s)
{
if (!s)
return ERROR;
memset(s->data, 0, MAXSIZE*sizeof(ElemType));
s->top = -1;
return OK;
}
//将栈清空
Status ClearStack(sqStack *s)
{
if (!s)
return ERROR;
s->top = -1;
return OK;
}
//若栈存在,返回true,否则返回false
Status StackEmpty(sqStack s)
{
if (s.top == -1)
return OK;
return ERROR;
}
// 若是栈存在,则插入新的元素e到栈S中并成为栈顶元素
Status Push(sqStack *s, ElemType e)
{
if (s->top == MAXSIZE||!s)
return ERROR;
s->top++;
s->data[s->top] = e;
return OK;
}
//若是栈存在且非空,删除栈顶元素,并用e返回其值
Status Pop(sqStack *s, ElemType *e)
{
if (!s || StackEmpty(*s) || !e)
return ERROR;
*e = s->data[s->top--];
return OK;
}
stack.c使用顺序栈
void PreOrderTraverseByStack(BiTree BT)
{
BiTree T = BT;
sqStack s;
InitStack(&s);
while (T || !StackEmpty(s))
{
while (T)
{
printf("%c", T->data);
Push(&s, T);
T = T->lchild;
}
if (!StackEmpty(s))
{
Pop(&s, &T);
T = T->rchild;
}
}
printf("
");
}
void InOrderTraverseByStack(BiTree BT)
{
BiTree T = BT;
sqStack s;
InitStack(&s);
while (T || !StackEmpty(s))
{
while (T)
{
Push(&s, T);
T = T->lchild;
}
if (!StackEmpty(s))
{
Pop(&s, &T);
printf("%c", T->data);
T = T->rchild;
}
}
printf("
");
}
void PostOrderTraverseByStack(BiTree BT)
{
BiTree T = BT;
sqStack s;
InitStack(&s);
while (T||!StackEmpty(s))
{
while (T)
{
Push(&s, T);
T = T->lchild;
}
if (!StackEmpty(s))
{
Pop(&s, &T);
if (!T->rchild||T->first==2)
{
printf("%c", T->data);
T = NULL;
}
else
{
T->first = 2;
Push(&s,T);
T = T->rchild;
}
}
}
printf("
");
}
//二叉树的二叉链表结点结构定义
typedef struct BiTNode //结点结构
{
TElemType data; //结点数据
int first; //对于非递归后序而言
struct BiTNode *lchild, *rchild; //左右孩子指针
}BiTNode, *BiTree;
注意:针对后序非递归遍历,我们需要为结点设置一个标识
int main()
{
BiTree T;
printf("1.CreateBiTree
");
CreateBiTree(&T);
printf("2.PreOrderTraverse
");
PreOrderTraverse(T, 0);
printf("3.InOrderTraverse
");
InOrderTraverse(T, 0);
printf("4.PostOrderTraverse
");
PostOrderTraverse(T, 0);
printf("5.PreOrderTraverseByStack
");
PreOrderTraverseByStack(T);
printf("6.InOrderTraverseByStack
");
InOrderTraverseByStack(T);
printf("7.PostOrderTraverseByStack
");
PostOrderTraverseByStack(T);
system("pause");
return 0;
}
(五)使用队列完成层序遍历
#include <stdio.h>
#include <stdlib.h>
#include "BinT.h"
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef BiTree ElemType;
typedef int Status;
//设置队列的数据结点
typedef struct QNode
{
ElemType data; //存放队列中的数据
struct QNode* next; //队列结点的指针域
}QNode, *QNodePtr;
//设置队列的结构体
typedef struct
{
QNodePtr front, rear; //队列头尾指针
}LinkQueue;
//四个基础操作
Status InitQueue(LinkQueue *Q); //初始化操作,建立一个空队列Q
Status ClearQueue(LinkQueue *Q);//将队列清空
Status QueueEmpty(LinkQueue Q); //若队列为空,返回true,否则返回false
Status EnQueue(LinkQueue *Q, ElemType e); //若是队列存在,则插入新的元素e入队为队尾
Status DeQueue(LinkQueue *Q, ElemType *e); //若是队列存在且非空,进行出队操作,用e接收数据
queue.h
#include "queue.h"
//初始化操作,建立一个空队列Q
Status InitQueue(LinkQueue *Q)
{
if (!Q)
return ERROR;
Q->front = Q->rear = (QNodePtr)malloc(sizeof(QNode));
if (!Q->front)
return ERROR;
Q->front->next = Q->rear->next = NULL;
return OK;
}
//将队列清空,保留头结点,注意队尾指针
Status ClearQueue(LinkQueue *Q)
{
QNodePtr head = Q->front->next; //获取开始结点
QNodePtr cur; //游标指针
if (!Q)
return ERROR;
while (head) //将数据全部释放
{
cur = head;
head = head->next;
free(cur);
}
Q->rear = Q->front; //将队尾指向队头
Q->rear->next = Q->front->next = NULL; //记得:重点
return OK;
}
//若队列为空,返回true,否则返回false
Status QueueEmpty(LinkQueue Q)
{
if (!Q.front->next)
return TRUE;
return FALSE;
}
//若是队列存在,则插入新的元素e入队为队尾,注意还要考虑队尾指针
Status EnQueue(LinkQueue *Q, ElemType e)
{
if (!Q)
return ERROR;
QNodePtr q = (QNodePtr)malloc(sizeof(QNode));
if (!q)
return ERROR;
q->data = e;
q->next = Q->rear->next;
Q->rear->next = q;
Q->rear = q;
return OK;
}
//若是队列存在且非空,进行出队操作,用e接收数据,注意还要考虑队尾指针
Status DeQueue(LinkQueue *Q, ElemType *e)
{
QNodePtr q;
if (!Q || !e || QueueEmpty(*Q))
return ERROR;
q = Q->front->next; //开始结点
*e = q->data;
Q->front->next = q->next; //指针后移(这一步注意:重点,且易错)
if (Q->rear == q) //若是我们队列中只有一个结点,删除后需要修改队尾指针
Q->rear = Q->front;
free(q); //释放结点
return OK;
}
queue.c
void LevelOrderTraverseByQueue(BiTree T)
{
LinkQueue Q;
BiTree Tmp;
InitQueue(&Q);
if (!T)
return ;
EnQueue(&Q, T);
while (!QueueEmpty(Q))
{
DeQueue(&Q, &Tmp);
printf("%c", Tmp->data);
if (Tmp->lchild)
EnQueue(&Q, Tmp->lchild);
if (Tmp->rchild)
EnQueue(&Q, Tmp->rchild);
}
printf("
");
}