树递归与非递归遍历、总结点数以及叶子节点数、哈夫曼树、双亲法
1)二叉树的基本操作
(1)给出一棵二叉树,采用二叉链表存储结构,从键盘读入节点字符,序建立二叉树(例如,ABD#G###CE##FH###)
(2)分别采用递归或非递归算法,实现对该二叉树的先序、中序和后序遍历等基本操作,输出遍历结果。
(3)实现层次遍历二叉树并输出遍历序列。
2)二叉树的应用
(1)修改遍历算法,求出二叉树的结点总数和叶子结点数,输出结果。
(2)交换二叉树的左右子树。
(3)选作题:编写判定二叉树是否是完全二叉树的算法,再编程实现该算法。
(4)选作题: 编程实现哈夫曼树的构造算法。
3)选作题:树的存储结构及基本操作
采用双亲表示法存储一棵树,编程实现下列功能
①构造该树
②求某结点的双亲结点和所有孩子结点。
#include "stdio.h"
#include "string.h"
#include<iostream>
#include<conio.h>
#include<malloc.h>
#define MAXQSIZE 100
typedef char TElemType ;
typedef struct BiNode
{
TElemType data;
struct BiNode * lchild ,* rchild;
}BiNode ,*BiTree;
typedef struct{
struct BiNode *base[100];
int front,rear;
}SqQueue;
typedef struct{
struct BiNode *base[100];
int top;
}Sstack;
typedef struct{
TElemType data;
int parent;
} Pnode;
typedef struct{
Pnode node[MAXQSIZE];
int length;
}Tree;
typedef struct{
Pnode node[MAXQSIZE];
int front;
int rear;
}que;
typedef struct{
char data;
int weight;
int parent;
int lchild;
int rchild;
}HTNode,HuffmanTree;
typedef struct{
char code[10];
int start;
}Hfcode;
typedef struct{
char code[1000];
int length;
}Hcode;
HuffmanTree Ht[1000];
Hfcode hcode[1000];
/* 中序非递归遍历 */
void inorder(BiTree T)
{ Sstack s;
s.top=0;
BiTree p;
p=T;
while(p!=NULL || s.top!=0)
{
if (p!=NULL)
{ s.base[s.top]=p;
s.top =s.top+1;
p=p->lchild;
}
else
{ s.top =s.top-1;
p=s.base[s.top];
printf("%c",p->data);
p=p->rchild;
}
}
}
/* 层次遍历算法 */
void LevelOrderTraverse(BiTree T)
{ BiTree p;
SqQueue Q;
Q.rear=Q.front=0;
if (T)
{ Q.base[Q.rear]=T;
Q.rear=(Q.rear+1)%MAXQSIZE;
while (Q.front !=Q.rear)
{
p=Q.base[Q.front];
printf("%c",p->data);
Q.front=(Q.front+1)%MAXQSIZE;
if(p->lchild){
Q.base[Q.rear]=p->lchild;
Q.rear=(Q.rear+1)%MAXQSIZE;
}
if(p->rchild){
Q.base[Q.rear]=p->rchild;
Q.rear=(Q.rear+1)%MAXQSIZE;
}
}
}
}
BiTree CreateBiTree(BiTree bt)
{ char ch;
BiTree h=NULL;
ch=getch();
if(ch=='#') bt=NULL;
else
{
if((bt=(BiNode *)malloc(sizeof(BiNode)))==NULL)
return NULL;
bt->data=ch;
printf("\n构造%C的左子树\n",ch);
bt->lchild=CreateBiTree(h);
printf("\n构造%C的右子树\n",ch);
bt->rchild=CreateBiTree(h);
}
return(bt);
}
void PreOrderTraverse(BiTree bt)
{ if (bt)
{ printf("%c",bt->data);
PreOrderTraverse(bt->lchild);
PreOrderTraverse(bt->rchild);
}
}
void InOrderTraverse(BiTree bt)
{
if(bt){
InOrderTraverse(bt->lchild);
printf("%c",bt->data);
InOrderTraverse(bt->rchild);
}
}
void PostOrderTraverse(BiTree bt)
{
if(bt){
PostOrderTraverse(bt->lchild);
PostOrderTraverse(bt->rchild);
printf("%c",bt->data);
}
}
void MenuList()
{
printf("\n\n\n**************************************************\n");
printf("**************** 二叉树的生成和遍历实验***********\n");
printf("**** 1 -------生成二叉树 ****\n");
printf("**** 2 -------先序遍历二叉树(含递归和非递归)****\n");
printf("**** 3 -------中序遍历二叉树(含递归和非递归)****\n");
printf("**** 4 -------后序遍历二叉树(含递归和非递归)****\n");
printf("**** 5 -------层次遍历 ****\n");
printf("**** 6 ------非递归中序遍历 ****\n");
printf("**** 7 ------二叉树的结点总数和叶子结点数 ****\n");
printf("**** 8 ------交换二叉树的左右子树 ****\n");
printf("**** 9 -----判断一棵树是否为完全二叉树 ****\n");
printf("**** 10 -----采用双亲表示法构造棵树 ****\n");
printf("**** 11 -----求某结点的双亲结点 ****\n");
printf("**** 12-----求某结点的所有孩子结点 ****\n");
printf("**** 13-----实现哈夫曼树的构造算法 ****\n");
printf("**** 0 -------结束运行 ****\n") ;
printf("**************************************************\n");
}
void Traversecount(BiTree T,int &count,int &count_leaf)
{
if(T){
count++;
if(T->lchild==NULL&&T->rchild==NULL){
count_leaf+=1;
}
Traversecount(T->lchild,count,count_leaf);
Traversecount(T->rchild,count,count_leaf);
}
}
void change_left_right(BiTree T)
{ //操作结果:交换二叉树T的左右子树
BiNode * p;
if (T)
{ change_left_right(T->lchild);
change_left_right(T->rchild);
p=T->lchild;
T->lchild=T->rchild;
T->rchild=p;
} }
int fullbitree(BiTree T){
if(!T){
return 0;
}
if((T->lchild==NULL&&T->rchild==NULL)||(T->lchild&&T->rchild==NULL)){
return 1;
}
return fullbitree(T->lchild)&fullbitree(T->rchild);
}
//
void safe_flush(FILE *fp){
int ch;
while((ch=fgetc(fp))!=EOF&&ch!='\n');
}
//构造双亲表示法的树
void createtree(Tree &tree){
char ch;
int i,j,k;
printf("请输入入数的结点个数:\n");
scanf("%d",&k);
tree.length=k;
printf("请输入树中结点的字符型值,需第一个输入根节点\n");
for(i=0;i<tree.length;i++){
printf("请输入第%d个节点的值:",i+1);
safe_flush(stdin);
scanf("%c",&ch);
tree.node[i].data=ch;
}
tree.node[0].parent=-1;//根节点的双亲下标设为1
printf("请输入结点的双亲存储位置下标\n") ;
for(i=1;i<tree.length;i++){
printf("请输入第%d个结点的双亲下标:",i+1);
scanf("%d",&j);
tree.node[i].parent=j;
}
}
void parent_find(Tree tree){
char ch;
int i,j;
printf("请输入要查找的双亲的结点:\n");
safe_flush(stdin);
scanf("%c",&ch);
for(i=0;i<tree.length;i++){
if(tree.node[i].data==ch)
break;
}
if(i>=tree.length){
printf("树中不存在值为%c的结点,查找失败\n",ch);
}
j=tree.node[i].parent;
if(j==-1){
printf("%c是根结点,没有双亲",tree.node[i].data);
}
else
printf("%c的双亲为%c \n",ch,tree.node[j].data);
}
//查找某结点的所有孩子
void child_find(Tree tree){
int i,j=0,k;
char ch;
printf("请输入你要找的所有孩子的节点值:\n");
safe_flush(stdin);
scanf("%c",&ch);
for(i=0;i<tree.length;i++){
if(tree.node[i].data==ch){
break;
}
}
k=i;
if(k>=tree.length){
printf("树中不存在值为%c的结点,查找失败",ch);
printf("\n");
}
for(i=0;i<tree.length;i++){
if(tree.node[i].parent==k){
j++;
printf("%c的第%d个孩子是:%c\n",ch,j,tree.node[i].data);
}
}
if(j==0)
printf("%c没有孩子结点!",ch);
}
//实现哈夫曼树的构造算法
void HmTree(HuffmanTree Ht[],int w[],char a[],int n){
//w存放n个字符的权值,均大于0
int m,i,j,min1,min2,s1,s2;
if(n<=1){
return;
}
m=2*n-1;
for(i=0;i<=n;i++){
Ht[i].weight=w[i-1];
Ht[i].data=a[i-1];
Ht[i].parent=0;
Ht[i].lchild=0;
Ht[i].rchild=0;
}
for(;i<=m;++i){
Ht[i].weight=0;
Ht[i].data='#';
Ht[i].parent=0;
Ht[i].lchild=0;
Ht[i].rchild=0;
}
for(i=n+1;i<=m;i++){
//创建哈夫曼树
s1=0;
s2=0;
min1=0;
for(j=0;j<=i-1;j++){
if(Ht[j].parent==0)
if(Ht[j].weight<min1||min1==0){
min1=Ht[j].weight;
s1=j;
}
}
min2=0;
for(j=0;j<=i-1;j++){
if(Ht[j].parent==0&&j!=s1)
if(min2==0||Ht[j].weight<min2){
min2=Ht[j].weight;
s2=j;
}
}
//
Ht[i].weight=Ht[s1].weight+Ht[s2].weight;
Ht[s1].parent=i;
Ht[s2].parent=i;
Ht[i].lchild=s1;
Ht[i].rchild=s2;
}
}
int main()
{
BiTree T;
int i=100;
int count=0,count_leaf=0;
MenuList();
Tree tree;
int m;
int n,w[100];
char a[20];
while(i!=0)
{
printf("请输入选择:");
scanf("%d" ,&i);
if (i==1)
{ printf("请输入二叉树的先序遍历序列,#代表空树:");
T=CreateBiTree(NULL);
}
if (i==2)
{
printf("先序递归遍历二叉树:");
PreOrderTraverse(T);
printf("\n") ;
}
if (i==3)
{ printf("中序递归遍历二叉树:");
InOrderTraverse(T);
printf("\n") ;
}
if (i==4)
{ printf("后序递归遍历二叉树:");
PostOrderTraverse(T);
printf("\n") ;
}
if (i==5)
{printf("层次递归遍历二叉树:");
LevelOrderTraverse(T);
printf("\n") ;
}
if (i==6)
{printf("中序非递归遍历二叉树:");
inorder(T);
printf("\n") ;
}
if (i==7)
{
Traversecount(T,count,count_leaf);
printf("二叉树的结点总数为%d\n",count);
printf("二叉树的叶子结点总数为%d\n",count_leaf);
printf("\n") ;
}
if (i==8)
{ printf("交换二叉树的左右子树\n");
change_left_right(T);
printf("\n") ;
}
if (i==9)
{ printf("判断一棵树是否为完全二叉树 \n");
int a= fullbitree(T);
if(a==1)
printf("是完全二叉树");
if(a==0)
printf("不是完全二叉树");
printf("\n") ;
}
if(i==10){
createtree(tree);
}
if(i==11){
parent_find(tree);
}
if(i==12){
child_find(tree);
}
if(i==13){
printf("请输入权值个数(小于20):\n");
scanf("%d",&n);
printf("请输入%d个权值:\n",n);
for(i=0;i<n;i++){
scanf("%d",&w[i]);
safe_flush(stdin);
printf("请输入%d个权值对应的字符:",n);
for(i=0;i<n;i++){
a[i]=getchar();
HmTree(Ht,w,a,n);
}
}
}
}
}