#include "StdAfx.h"
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//定义链式存储的二叉树类型
struct TreeNode
{
char data;//数据域
struct TreeNode *left;//左域
struct TreeNode *right;//右域
};
typedef TreeNode *BinTree;
//导入链队列相关
struct Node
{
BinTree data;//数据域
struct Node *next;//指针域
};
typedef struct Node *PNode;
struct Queue
{
PNode f;//f指向头结点
PNode r;//r指向尾结点
};
typedef struct Queue *LinkQueue;
LinkQueue SetNullQueue()
{
LinkQueue lqueue;
lqueue=(LinkQueue)malloc(sizeof(struct Queue));//为队列lqueue分配队列结构体那么大空间
if(lqueue!=NULL)//分配成功则使f,r指空
{
lqueue->f=NULL;
lqueue->r=NULL;
}
else
printf("alloc failure!");
return lqueue;
}
int IsNullQueue(LinkQueue lqueue)
{
return(lqueue->f==NULL);//若头指针指空则为空
}
void InQueue(LinkQueue lqueue,BinTree x)//x入队
{
PNode p;
p=(PNode)malloc(sizeof(struct Node));//申请一个结点空间p用于存放输入数据,由p指向
if(p!=NULL)
{
p->data=x;//放入数据至p
p->next=NULL;
if(IsNullQueue(lqueue))//若空队列则特殊处理
{
lqueue->f=p;
lqueue->r=p;
}
else//不是空队列则按以下操作
{
lqueue->r->next=p;//队尾结点指针指向p
lqueue->r=p;//使队尾指针指向p指向的结点空间p
}
}
else
printf("alloc failure!");
}
void OutQueue(LinkQueue lqueue)
{
PNode p;
if(IsNullQueue(lqueue))//判空
printf("empty!");
else
{
p=lqueue->f;//使p指向头结点
lqueue->f=lqueue->f->next;//头指针指向头结点的next所指
free(p);//释放头结点
}
}
BinTree FrontQueue(LinkQueue lqueue)
{
if(lqueue->f==NULL)//判空
{
printf("empty!");
return 0;
}
else
return (lqueue->f->data);//返回头结点数据域
}
//导入链栈相关
typedef int DataType;
typedef struct Node *top;//Node刚才链队列那里已经定义过了所以这里不重复定义了
typedef struct Node *LinkStack;
LinkStack SetNullStack()
{
LinkStack top=(LinkStack)malloc(sizeof(struct Node));//申请栈顶空间,top指向
if(top!=NULL)
top->next =NULL;
else
printf("alloc failure");
return top;//返回栈顶指针
}
int IsNullStack(LinkStack top)
{
return(top->next == NULL);
}
void Push(LinkStack top,BinTree x)//x进栈
{
PNode p=(PNode)malloc(sizeof(struct Node));//结点p,用于存放新进栈数据
if(p!=NULL)
{
p->data =x;
p->next =top->next ;//使p指针域为NULL
top->next =p;
}
else
printf("alloc failure!\n");
}
void Pop(LinkStack top)
{
PNode p;
if(IsNullStack(top))
printf("empty!\n");
else
{
p=top->next ;//孤立p然后删除
top->next =p->next ;
free(p);
}
}
BinTree top_seq(LinkStack top)
{
if(IsNullStack(top))
printf("empty!\n");
else
return top->next ->data ;
}
//递归建立二叉树
BinTree create1()
{
BinTree bt;
char ch;
scanf(" %c",&ch);//输入想放入二叉树根节点的字符,若想让某一个为空则输入@去填充(%前加空格避免将回车字符也作为输入数据)
if(ch=='@')
bt=NULL;
else
{
bt=(BinTree)malloc(sizeof(struct TreeNode));
bt->data=ch;
bt->left=create1();//递归构造左子树
bt->right=create1();//递归构造右子树
}
return bt;
}
//非递归建立二叉树(要补充成完全二叉树,即除最后一层外其余各层都满的,且最后一层结点从左到右要挨着不能留空隙)
BinTree create2()
{
LinkQueue queue=SetNullQueue();//建立空队列
BinTree s,p,bt;
int count=-1;//设置计数器
char ch;
scanf(" %c",&ch);//输入根节点数据
bt=NULL;
while(ch!='#')//输入#则结束
{
if(ch=='@')//若输入的是@则为虚结点,s指空,计数器加一
{
s=NULL;
count++;
}
else//若输入不为虚结点,将ch放入s空间的数据域内,s不指空,计数器加一
{
s=(BinTree)malloc(sizeof(struct TreeNode));
s->data=ch;
s->left=NULL;
s->right=NULL;
count++;
}
InQueue(queue,s);//将虚结点和新结点入队
if(count==0)//若计数器为0则s为根节点,bt指向(之后会有很多结点加进去构成树)
bt=s;
else
{
p=FrontQueue(queue);//p指队头(父节点)
if(s!=NULL && p!=NULL)//若s及其父节点都不是虚结点
if(count%2==1)//cout为奇,新结点作为左儿子插入父节点
p->left=s;
else
p->right=s;//为偶则作为右儿子插入父节点
if(count%2==0)//count为0说明已经处理到右儿子了,即左右两儿子已经处理完成,头结点出队
OutQueue(queue);
}
scanf(" %c",&ch);
}
return bt;
}
//深度优先遍历(递归先序遍历)
void preOrder1(BinTree bt)
{
if(bt)
{
printf("%c",bt->data);//若数不为空则按上左右依次遍历
preOrder1(bt->left);
preOrder1(bt->right);
}
}
//深度优先遍历(非递归先序遍历)
void preOrder2(BinTree bt)
{
LinkStack lstack=SetNullStack();//建立空链栈
BinTree p=bt;
if(bt)//bt不为空则将其根节点压入链栈
Push(lstack,bt);
while(!IsNullStack(lstack))//若连栈不为空
{
p=top_seq(lstack);//p取链栈顶元素
Pop(lstack);//顶元素出栈
while(p)//当p不为空
{
printf("%c",p->data);//输出其数据
if(p->right)//若右儿子不为空则右进栈
Push(lstack,p->right);
p=p->left;//p取其左儿子再次判断
}
}
}
//深度优先遍历(递归中序遍历)
void inOrder1(BinTree bt)
{
if(bt)//若数不为空则按左上右依次遍历
{
inOrder1(bt->left);
printf("%c",bt->data);
inOrder1(bt->right);
}
}
//深度优先遍历(非递归中序遍历)
void inOrder2(BinTree bt)
{
LinkStack lstack=SetNullStack();//建立空链栈
BinTree p=bt;
if(bt)//bt不为空则将其根节点压入链栈
Push(lstack,bt);
p=p->left;//进入左子树
while(p||!IsNullStack(lstack))//若栈不为空或者左儿子不为空
{
while(p)//进入左子树的左子树
{
Push(lstack,p);//左儿子进栈
p=p->left;
}
p=top_seq(lstack);//p取栈顶元素
Pop(lstack);//栈顶元素出栈
printf("%c",p->data);//输出栈顶元素
p=p->right;//判断右子树
}
}
//深度优先遍历(递归后序遍历)
void postOrder1(BinTree bt)
{
if(bt)//若数不为空则按左右上依次遍历
{
postOrder1(bt->left);
postOrder1(bt->right);
printf("%c",bt->data);
}
}
//深度优先遍历(非递归后序遍历)
void postOrder2(BinTree bt)
{
LinkStack lstack=SetNullStack();//建立空链栈
BinTree p=bt;
while(p||!IsNullStack(lstack))//若栈不为空或者根节点不为空
{
while(p)
{
Push(lstack,p);//根节点进栈
p=p->left?p->left:p->right;//若有左儿子则p为左儿子否则为右儿子
}
p=top_seq(lstack);//p取栈顶元素
Pop(lstack);//栈顶元素出栈
printf("%c",p->data);//输出栈顶元素
if(!IsNullStack(lstack)&&(top_seq(lstack)->left==p))//从左子树退回进入右子树
p=top_seq(lstack)->right;
else
p=NULL;//从右子树退回上一级
}
}
//广度优先遍历(层序遍历),根节点开始一层一层往下遍历,同一层按从左到右遍历(使用链队列)
void levelOrder(BinTree bt)
{
BinTree p;
LinkQueue queue=SetNullQueue();//创建空队列queue
if(bt)//bt非空则...
{
p=bt;
InQueue(queue,bt);//根节点入队
while(!IsNullQueue(queue))//队列不空时执行循环
{
p=FrontQueue(queue);
OutQueue(queue);//根节点出队
printf("%c",p->data);//打印出队的所存放数据
if(p->left!=NULL)//左儿子进队
InQueue(queue,p->left);
if(p->right!=NULL)//右儿子进队
InQueue(queue,p->right);
}
}
}
//统计二叉树叶子节点数
int LeafNode(BinTree bt)
{
if(bt==NULL)//若二叉树为空,则叶子结点数为0
return 0;
else//若二叉树不为空
{
if(bt->left==NULL && bt->right==NULL)//左右儿子为空,则为叶子结点
return 1;
else
return( LeafNode(bt->left) + LeafNode(bt->right) );//遍历左右子树叶子结点数
}
}
//统计二叉树深度(左右子树深度更高的那个+1)
int deep(BinTree bt)
{
if(bt==NULL)
return 0;
else
{
int i=deep(bt->left);//递归计算左子树深度
int j=deep(bt->right);//递归计算右子树深度
int max=i>j?i:j;//判断两子树深度更高的那个
return max+1;//+1
}
}
//复制一颗二叉树(先复制左子树再复制右子树,最后复制结点数据)
BinTree copy(BinTree bt1)
{
BinTree bt2;
if(bt1)
{
bt2=(BinTree)malloc(sizeof(struct TreeNode));
if(bt2)
{
bt2->left=copy(bt1->left);//递归复制左子树
bt2->right=copy(bt1->right);//递归复制右子树
bt2->data=bt1->data;
return bt2;
}
else
printf("alloc failure");
}
else
return 0;
}
//主函数
int main()
{
BinTree bt1=create1();//递归构建一颗二叉树bt1
preOrder1(bt1);//递归先序遍历
printf("\n");
preOrder2(bt1);//非递归先序遍历
printf("\n");
inOrder1(bt1);//递归中序遍历
printf("\n");
inOrder2(bt1);//非递归中序遍历
printf("\n");
postOrder1(bt1);//递归后序遍历
printf("\n");
postOrder2(bt1);//非递归后序遍历
printf("\n");
levelOrder(bt1);//层序遍历
printf("\n");
int i=LeafNode(bt1);//求叶子结点
printf(" %d",i);
printf("\n");
int j=deep(bt1);//求深度
printf(" %d",j);
printf("\n");
BinTree bt2=copy(bt1);//复制二叉树
preOrder1(bt2);
printf("\n");
BinTree bt3=create2();//非递归构建一颗二叉树bt2
preOrder1(bt3);//递归先序遍历
printf("\n");
system("pause");
}
数据结构—二叉树
最新推荐文章于 2024-08-23 08:14:22 发布