zoukankan      html  css  js  c++  java
  • 【二叉树系列】二叉树课程大作业

    本博客将以代码的形式详细讲解二叉树的所有算法,包括创建二叉树,二叉树的三种遍历方式,二叉树的各种属性算法,如:求高度,求叶子节点数,求节点数,以及二叉树最常见的应用哈夫曼树,代码如下:

    # include<stdio.h>
    # include<string.h>
    # include<conio.h>
    # include<stdlib.h>
    # define N 1
    # define M 2*N-1
    typedef char * HC[N+1];
    typedef struct bt
    {
    	char x;
    	struct bt *lchild;
    	struct bt *rchild;
    }bt,*pbt;
    typedef struct 
    {
    	int parent;
    	int weight, lchild, rchild;
    }HT[M+1];
    void creatbt(pbt *root)
    {
    	char ch=getchar();
    	if(ch==' ')
    		*root=NULL;
    	else
    	{
    		*root=(pbt)malloc(sizeof(bt));
    		(*root)->x=ch;
    		creatbt(&((*root)->lchild));
    		creatbt(&((*root)->rchild));
    	}
    }
    void preorder(pbt root)
    {
    	if(root!=NULL)
    	{
    		printf("%c",root->x);
    		preorder(root->lchild);
    		preorder(root->rchild);
    	}
    }
    void inorder(pbt root)
    {
    	if(root!=NULL)
    	{
    		inorder(root->lchild);
    		printf("%c",root->x);
    		inorder(root->rchild);
    	}
    }
    void postorder(pbt root)
    {
    	if(root!=NULL)
    	{
    		postorder(root->lchild);
    		postorder(root->rchild);
    		printf("%c",root->x);
    	}
    }
    int btdepth(pbt root,int h)
    {
    	static int depth=0;
    	if(root!=NULL)
    	{
    		if(h>depth) depth=h;
    		btdepth(root->lchild,h+1);
    		btdepth(root->rchild,h+1);
    	}
    	return depth;
    }
    int nodenum(pbt root)
    {
    	static int n=0;
    	if(root!=NULL)
    	{ 
    		n++;
    		nodenum(root->lchild);
    		nodenum(root->rchild);
    	}
    	return n;
    }
    int leafnum(pbt root)
    {
    	static int n=0;
    	if(root!=NULL)
    	{
    		leafnum(root->lchild);
    		leafnum(root->rchild);
    		if((root->lchild==NULL)&&(root->rchild==NULL))
    			n++;
    	}
    	return n;
    }
    void select(HT ht,int n,int *x,int *y)
    {
    	int i,min1=100,min2=200;
    	for(i=1;i<=n;i++)
    	{
    		if(ht[i].parent==0&&ht[i].weight<min1)
    		{
    			min1=ht[i].weight;
    			*x=i;
    		}
    	}
    	for(i=1;i<=n;i++)
    	{
    		if(ht[i].parent==0&&ht[i].weight<min2&&i!=*x)
    		{
    			min2=ht[i].weight;
    			*y=i;
    		}
    	}
    
    
    }
    void hafuman(HT ht,int w[],int n)
    {
    	int i,k,m,x,y;
    	for(i=1;i<=n;i++)
    	{
    		ht[i].weight=w[i];
    		ht[i].parent=ht[i].lchild=ht[i].rchild=0;
    	}
    	m=2*n-1;
    	for(i=n+1;i<=m;i++)
    	{
    		ht[i].parent=ht[i].lchild=ht[i].rchild=0;
    	}
    	for(i=n+1;i<=m;i++)
    	{
    		select(ht,i-1,&x,&y);//选择parent为0且权值最小的结点
    		ht[i].weight=ht[x].weight+ht[y].weight;
    		ht[i].lchild=x;
    		ht[i].rchild=y;
    		ht[x].parent=ht[y].parent=i;
    	}
    }
    void hafumancode(HT ht,HC hc,int n)
    {
    	int i,c,p,start;
    	char * cd=(char *)malloc(n*sizeof(char));
    	cd[n-1]='';//此处的cd用来存储当前哈夫曼码,可供循环利用,相当于一个暂存器
    	for(i=1;i<=n;i++)//求n个叶子结点的哈夫曼码
    	{
    		start=n-1;
    		c=i;//因为下面会循环更新孩子结点,所以不能用i(否则第一次for循环后i可能就不再是1),可将i的值提前赋给c
    		p=ht[i].parent;
    		while(p!=0)//只要p不是根结点
    		{
    			start--;//此语句用来循环更新存储下标
    			if(ht[p].lchild==c)
    				//cd[i]='0';//错误。注意应从叶子结点开始向上推
    				cd[start]='0';
    			else
    				//cd[i]='1';
    				cd[start]='1';
    			c=p;//此语句用来循环更新孩子结点
    			p=ht[p].parent;
    		}
    		hc[i]=(char *)malloc((n-start)*sizeof(char));
    		strcpy(hc[i],&cd[start]);
    	}
    	free(cd);
    	for(i=1;i<=n;i++)
    	{
    		//printf("%d的哈夫曼码为%s
    ",ht[i],hc[i]);错误,ht[i]为结构数组,应写其成员
    		printf("%d的哈夫曼码为%s
    ",ht[i].weight,hc[i]);
    	}
    
    }
    void main()
    {
    	int n;
    	pbt root;
    	printf("		-----------------------------------------
    ");
    	printf("		1.创建二叉树          2.遍历二叉树
    ");
    	printf("		3.二叉树的属性        4.哈夫曼树
    ");
    	printf("		5.退出
    ");
    	printf("		-----------------------------------------
    ");
    	while(1)
    	{
    		printf("请选择功能模块(1-5)
    ");
    		scanf("%d",&n);
    		//char ch=getche();
    		getchar();
    		switch(n)
    		{
    			case 1:{printf("请以先序扩展创建二叉树(空结点用空格代替)
    ");creatbt(&root);}break;
    			case 2:
    			{
    				
    				printf("遍历二叉树
    ");
    				printf("		[1]先序遍历
    ");
    				printf("		[2]中序遍历
    ");
    				printf("		[3]后序遍历
    ");
    				printf("		[4]返回主菜单
    ");
    				while(1)
    				{
    					int n;
    					printf("请选择(1-4):
    ");
    					scanf("%d",&n);
    					if(1==n)
    						preorder(root);
    					if(2==n)
    						inorder(root);
    					if(3==n)
    						postorder(root);
    					//else//不能这样写,因为这个else只能与上一个if配对,所以当n!=3时break都会执行
    					if(n==4)
    						break;
    				}
    			   }break;
    			case 3:
    			{
    				int h=1,n;
    				printf("二叉树属性
    ");
    				printf("		[1]二叉树高度
    ");
    				printf("		[2]二叉树结点数
    ");
    				printf("		[3]二叉树叶子结点
    ");
    				printf("		[4]返回主菜单
    ");
    				while(1)
    				{
    					printf("请选择:(1-4)
    ");
    					scanf("%d",&n);
    					if(1==n)
    						printf("该二叉树的高度为%d
    ",btdepth(root,h));
    					if(2==n)
    						printf("该二叉树的结点数为%d
    ",nodenum(root));
    					if(3==n)
    						printf("该二叉树的叶子结点数为%d
    ",leafnum(root));
    					if(n==4)
    						break;
    				}
    
    			}break;
    			case 4:
    				{
    					HT ht;
    					HC hc;
    					int n,i;
    					printf("请输入叶子结点的个数
    ");
    					scanf("%d",&n);
    					int * w=(int *)malloc((n+1)*sizeof(int));//此语句必须位于scanf的下面
    					for(i=1;i<=n;i++)
    					{
    						printf("请输入第%d个叶子结点的权值
    ",i);
    						scanf("%d",&w[i]);
    					}
    					hafuman(ht,w,n);hafumancode(ht,hc,n);
    				}break;
    			case 5:exit(1);
    		}
    	}
    
    }

    程序运行结果如下:




    注意对于同一个二叉树,哈夫曼码的结果不唯一,上述输出只是一种情况。

  • 相关阅读:
    JS中const的使用
    JS的作用域,闭包的理解
    python中函数的默认参数是空数组
    asp.net 导出 Excel
    asp.net 导出 Excel 身份证格式显示格式问题
    HTML5
    JQuery中checkbox选择器
    JQuery中DOM操作(一)
    PL/SQL 创建用户及权限操作
    PL/SQL 表约束
  • 原文地址:https://www.cnblogs.com/hainange/p/6334054.html
Copyright © 2011-2022 走看看