树、二叉树的基本操作(数据结构)

这篇博客介绍了如何使用C++实现二叉树的各种遍历方式,包括递归和非递归的先序、中序、后序遍历以及层次遍历。此外,还涉及到了二叉树节点总数和叶子节点的计算、左右子树交换、完全二叉树的判断以及使用双亲表示法存储和操作树的方法。同时,提到了哈夫曼树的构造算法,提供了完整的代码实现。
摘要由CSDN通过智能技术生成

树递归与非递归遍历、总结点数以及叶子节点数、哈夫曼树、双亲法

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);
					
				}
			}
			
		}
		
		
    }

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值