二叉树基本操作
实验要求:
1.按先序序列构造一棵二叉链表表示的二叉树T;
2.对这棵二叉树进行递归遍历:先序、中序、后序以及层次遍历遍历序列,分别输出结点的遍历序列;
3. 对这棵树用非递归方式进行遍历:先序、中序以及后序遍历序列,分别输出结点的遍历序列;
4.求二叉树的深度/结点数目/叶结点数目;
5.将二叉树每个结点的左右子树交换位置;
6. 设计二叉树的双序遍历算法(双序遍历是指对于二叉树的每一个结点来说,先访问这个结点,再按双序遍历它的左子树,然后再一次访问这个结点,接下来按双序遍历它的右子树);
7. 计算二叉树最大宽度(二叉树的最大宽度是指二叉树所有层中结点个数的最大值);
8. 求二叉树中第一条最长的路径长度,并输出此路径上各结点。
#include<stdio.h>
#include<stdlib.h>
#define STACKSIZE 20
typedef struct tree_node{
char data;
struct tree_node *LC;
struct tree_node *RC;
}TreeNode,*Tree;
typedef struct queue_node{
struct tree_node *treenode;
struct queue_node *next;
}QueueNode;
typedef struct queue{
struct queue_node *front;
struct queue_node *rear;
}Queue;
void CreatPre(Tree *b);
void ShowPre(Tree b);
void ShowIn(Tree b);
void ShowPost(Tree b);
void LevelShow(Tree T);
void DoubleShow(TreeNode *T);
void InitQueue(Queue *q);
int IsQueueEmpty(Queue *q);
void InQueue(Queue *q,QueueNode *p);
void OutQueue(Queue *q,QueueNode *p);
void PreOrder(TreeNode *bt);
void InOrder(TreeNode *bt);
void PostOrder(TreeNode *bt);
int TreeHeight(Tree root);
int LevelWidth(Tree root,int level);
int Width(Tree root);
int CountAll(Tree root);
int CountLeaf(Tree root);
void ShowLeaf(Tree root);
void ExChangeTree(Tree T);
int Find(Tree root);
void PrintLength(Tree root);
//按先序序列构造一棵二叉链表表示的二叉树T
void CreatPre(Tree *b){
char ch;
scanf("%c",&ch);
if(ch=='*')
*b=NULL;
else{
*b=(Tree)malloc(sizeof(TreeNode));
(*b)->data=ch;
CreatPre(&(*b)->LC);
CreatPre(&(*b)->RC);
}
}
//前序遍历
void ShowPre(Tree b){
if(b){
printf("%c ",b->data);
ShowPre(b->LC);
ShowPre(b->RC);
}
}
//中序遍历
void ShowIn(Tree b){
if(b){
ShowIn(b->LC);
printf("%c ",b->data);
ShowIn(b->RC);
}
}
//后序遍历
void ShowPost(Tree b){
if(b){
ShowPost(b->LC);
ShowPost(b->RC);
printf("%c ",b->data);
}
}
//层次遍历
void LevelShow(Tree T){
Queue *Q;
Queue m_queue;
QueueNode *p,*q;
if(!T)
return;
Q=&m_queue;
InitQueue(Q);
p=(QueueNode *)malloc(sizeof(QueueNode));
p->next=NULL;
p->treenode=T;
InQueue(Q,p);
while(!IsQueueEmpty(Q)){
OutQueue(Q,&q);
printf("%c ",q->treenode->data);
if(q->treenode->LC){
p=(QueueNode *)malloc(sizeof(QueueNode));
p->next=NULL;
p->treenode=q->treenode->LC;
InQueue(Q,p);
}
if(q->treenode->RC){
p=(QueueNode *)malloc(sizeof(QueueNode));
p->next=NULL;
p->treenode=q->treenode->RC;
InQueue(Q,p);
}
}
}
//双序遍历
void DoubleShow(TreeNode *T)
{
if(T)
{
printf("%c ",T->data);
DoubleShow(T->LC);
printf("%c ",T->data);
DoubleShow(T->RC);
}
}
//队列操作
//初始化队列
void InitQueue(Queue *q){
//简单初始化
q->front=NULL;
q->rear=NULL;
}
//队列是否为空
int IsQueueEmpty(Queue *q){
if(q->front)
return 0;
else
return 1;
}
//进队
void InQueue(Queue *q,QueueNode *p){
if(IsQueueEmpty(q)){
q->front=p;
q->rear=p;
}else{
q->rear->next=p;
q->rear=p;
}
}
//出队
void OutQueue(Queue *q,QueueNode **p){
*p=q->front;
if(q->front==q->rear){
q->front=NULL;
q->rear=NULL;
}else{
q->front=q->front->next;
}
}
//先序非递归遍历
void PreOrder(TreeNode *bt){
TreeNode *s[STACKSIZE];
int i=0;
TreeNode *p;
if(!bt)
return;
else
p=bt;
do{
while(p){
printf("%c ",p->data);
s[i++]=p;
p=p->LC;
}
if(i!=0){
p=s[--i];
p=p->RC;
}
}while(p||i!=0);
}
//中序非递归遍历
void InOrder(TreeNode *bt){
TreeNode *s[STACKSIZE];
int i=0;
TreeNode *p;
if(!bt)
return;
else
p=bt;
do{
while(p){
s[i++]=p;
p=p->LC;
}
if(i!=0){
p=s[--i];
printf("%c ",p->data);
p=p->RC;
}
}while(p||i!=0);
}
//后序非递归
void PostOrder(TreeNode *bt){
TreeNode *s[STACKSIZE];
TreeNode *r[STACKSIZE];
int top1 = -1, top2=-1;
s[++top1] = bt;
while(top1!=-1){
bt = s[top1--];
r[++top2] = bt; //只用来反向最后的一趟的结果
/*
由于栈的特点就是后进先出,所以左子树先入栈,然后出去的时候
是右子树先出栈,故而这里就完成了第一次的左右子树的交换
*/
if(bt->LC!=NULL){
s[++top1] = bt->LC;
}
if(bt->RC!=NULL){
s[++top1] = bt->RC;
}
}
while(top2!=-1){
bt = r[top2--];
printf("%c ",bt->data);
}
}
//4.求二叉树的深度/结点数目/叶结点数目
//二叉树深度
int TreeHeight(Tree root){
int LCHeight,RCHeight;
if(root==NULL)
return 0;
LCHeight=TreeHeight(root->LC);
RCHeight=TreeHeight(root->RC);
return (LCHeight>RCHeight)?(1+LCHeight):(1+RCHeight);
}
//某层宽度
int LevelWidth(Tree root,int level){
if(!root)return 0;
else
{
if(level==1)return 1;
level=LevelWidth(root->LC,level-1)+LevelWidth(root->RC,level-1);
}
return level;
}
//取得二叉树最大宽度
int Width(Tree root){
int width,i;
int w[20];
for(i=0;i<20;i++)w[i]=0;
if(!root)width=0;
else
{
for(i=0;i<=TreeHeight(root);i++)w[i]=LevelWidth(root,i+1);
}
i=0;
while(w[i])
{
if(w[i]>width)width=w[i];
i++;
}
return width;
}
//求所有结点的个数
int CountAll(Tree root){
if(root==NULL)
return 0;
return CountAll(root->LC)+CountAll(root->RC)+1;
}
//求叶子结点的个数
int CountLeaf(Tree root){
if(root==NULL)
return 0;
if(root->LC==NULL&&root->RC==NULL)
return 1;
else{
return CountLeaf(root->LC)+CountLeaf(root->RC);
}
}
//输出叶子结点
void ShowLeaf(Tree root){
if(root==NULL)
return;
if(root->LC==NULL&&root->RC==NULL)
printf("%c ",root->data);
else{
ShowLeaf(root->LC);
ShowLeaf(root->RC);
}
}
//将二叉树每个结点的左右子树交换位置
void ExChangeTree(Tree T){
Tree temp;
if (T)
{
temp = T->RC;
T->RC = T->LC;
T->LC = temp;
ExChangeTree(T->LC);
ExChangeTree(T->RC);
}
else
{
return;
}
}
//为二叉树的节点赋层号
int Find(Tree root){
if(!root->LC&&!root->RC){
return 0;
}else if(root->LC)
return Find(root->LC)+1;
else if(root->RC)
return Find(root->RC)+1;
else{
if(Find(root->LC)>Find(root->RC))
return Find(root->LC)+1;
else
return Find(root->RC)+1;
}
}
//输出最长路径
void PrintLength(Tree root){
if(root->LC&&root->RC){
printf("%c ",root->data);
if(Find(root->LC)>=Find(root->RC))
PrintLength(root->LC);
else
PrintLength(root->RC);
}
else if(root->LC){
printf("%c ",root->data);
PrintLength(root->LC);
}
else if(root->RC){
printf("%c ",root->data);
PrintLength(root->RC);
}
else
printf("%c ",root->data);
}
int main(){
Tree T;
printf("输入二叉树的前序遍历序列,用*代替空节点:\n");
CreatPre(&T);
printf("\n\n前序遍历:");
ShowPre(T);
printf("\n\n中序遍历:");
ShowIn(T);
printf("\n\n后序遍历:");
ShowPost(T);
printf("\n\n层次遍历:");
LevelShow(T);
printf("\n\n双序遍历:");
DoubleShow(T);
printf("\n\n");
printf("\n先序非递归遍历:");
PreOrder(T);
printf("\n\n中序非递归遍历:");
InOrder(T);
printf("\n\n后序非递归遍历:");
PostOrder(T);
printf("\n");
printf("\n第一条最长路径长度:");
PrintLength(T);
printf("\n");
printf("\n二叉树深度为: %d",TreeHeight(T));
printf("\n\n最大宽度: %d",Width(T));
printf("\n\n二叉树结点数目: %d",CountAll(T));
printf("\n\n二叉树叶结点:");
ShowLeaf(T);
printf("\n二叉树叶结点数目: %d",CountLeaf(T));
printf("\n");
printf("\n\n交换前二叉树先序遍历:");
PreOrder(T);
ExChangeTree(T);
printf("\n\n交换二叉树左右子树完成!\n");
printf("\n\n交换后二叉树先序遍历:");
PreOrder(T);
printf("\n");
return 0;
}