数据结构课程设计-二叉树操作系统

二叉树操作系统(哈夫曼树)头文件部分:
int a[1000];
BTree CreateHuf(ElemType a[],int n)      //根据数组a中n 个权值建立一棵哈夫曼树,返回树根指针
{
	int i,j;
    BTree *t1,t2;
    t1=(BTree *)malloc(n*sizeof(BTree));      //二级指针
/*	for(i=0;i<n;i++)
		t1[i]=(BTree)malloc(sizeof(BTNode));*/
	for(i=0;i<n;i++)            //初始化t1指针数组,构建n棵只含有根节点的树 
    {
		t1[i]=(BTree)malloc(sizeof(BTNode));
		t1[i]->ans=a[i];      //n个叶子节点的权重		
        t1[i]->lchild=NULL;     
        t1[i]->rchild=NULL;    //各个叶子节点的初始化操作
    }
	for(i=1;i<n;i++)      //向上取n-1次父亲节点,模拟哈夫曼树的过程就知道了 
    {   
		int First_min=-1,Second_min;           //c表示森林中权值最小的根节点的下标,d表示权值第二小的根节点的下标
        for(j=0;j<n;j++)           //让c,d分别指向森林中的第一棵树和第二棵树 
        {  
			if(t1[j]!=NULL&&First_min==-1)
            {              //t1[j]不到数组的尾部不可能是空指针
				First_min=j;          
                continue;  //即第一次后就有c!=-1了
            }
            if(t1[j]!=NULL)
            {
				Second_min=j;         
                break;      //注意break
            }
        }   
        for(j=Second_min;j<n;j++)          //从森林中找出权值最小的两棵树 
        {  
			if(t1[j]!=NULL)
			{
				if(t1[j]->ans<t1[First_min]->ans)
                { 
                    Second_min=First_min;
                    First_min=j;
                }
                else if(t1[j]->ans<t1[Second_min]->ans)
                    Second_min=j;
            }
		}    
        t2=(BTree)malloc(sizeof(BTNode));       //将找出的两棵树合并成一棵树
        t2->ans=t1[First_min]->ans+t1[Second_min]->ans;
        t2->lchild=t1[First_min];          //左孩子存放最小的能够一定程度上是最优二叉树是唯一的 
        t2->rchild=t1[Second_min];
        t1[First_min]=t2;
        t1[Second_min]=NULL;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
    }
    free(t1);    
    return t2;             //返回整个哈夫曼树的树根 
}

void Print_BTree(BTree root)  
{  
    if(root!=NULL)  
    {  
        printf("%d", root->ans);            //输出根结点的值  
        if(root->lchild!=NULL||root->rchild!=NULL)  
        {  
            printf("(");  
            Print_BTree(root->lchild);          //输出左子树  
            if(root->rchild!=NULL)  
                printf(",");  
            Print_BTree(root->rchild);   //输出右子树  
            printf(")");  
        }  
    }  
}  

void Hufcoding(BTree root,int len,FILE *fp,FILE *fp2)  //编码 
{
	static int c[10];     //如果我这里不加static那么这里就是自动局部变量,每次递归到这里后又重新分配内存空间大小
    int i;
    if(root!=NULL)         //树不为空 
    {
		if(root->lchild==NULL&&root->rchild==NULL)       //为叶子节点就打印出来
        {
			fprintf(fp,"%d\n",root->ans);
            for(i=0;i<len;i++)
            {
				fprintf(fp,"%d",c[i]);
				fprintf(fp2,"%d",c[i]);
			}
			fprintf(fp,"%c",'\n');
        }
        else             //访问到非叶子结点时分别向左右子树递归调用,并把分支上的0、1编码保存到数组a     
        {
			c[len]=0; 
            Hufcoding(root->lchild,len+1,fp,fp2);
            c[len]=1;           //c[]是标记数组吗
            Hufcoding(root->rchild,len+1,fp,fp2);
        }
    }
}

void Decoding_HuffumanTree(BTree root,FILE *fp1)   //根据哈夫曼树的结构+编码序列得出译码序列
{
	FILE *fp3;
	if((fp1=fopen("coding.txt","r"))==NULL)       //编码文件
	{
		printf("编码文件打开失败,请检查错误.\n");
		return ;
	}
	if((fp3=fopen("Decoding.txt","w+"))==NULL)    //译码文件
	{
		printf("译码文件创建失败,请检查错误.\n");
		return ;
	}
	char *q=NULL;
	BTree head=root;
	q=(char *)malloc(sizeof(char));           //一颗哈夫曼树总共有2*n-1个节点    
	for(*q=fgetc(fp1);!feof(fp1);)        //以字符方式进行文件读写操作
	{
		printf("%c",*q);
		*q=fgetc(fp1);     //fgetc()是每再进行一次读操作时才会自动移指针指向
	}
	rewind(fp1);
	*q=fgetc(fp1);
	while(head)
	{
		if(feof(fp1))
			break;
		if(*q=='0')
			head=head->lchild;
		if(*q=='1')
			head=head->rchild;
		if((NULL==head->lchild)&&(NULL==head->rchild))
		{
			fprintf(fp3,"%d\n",head->ans);
			head=root;
		}
		*q=fgetc(fp1);
	}
	fclose(fp1);
	fclose(fp3);
}
			
void Fuction_HuffumanTree(BTree root)
{
	int chioce,n,i;
	system("cls");
	printf("\t    最优二叉书应用             \n");
    printf("\t     1. 初始操作               \n"); 
    printf("\t     2. 编码操作               \n"); 
    printf("\t     3. 译码操作               \n"); 
    printf("\t     4. 打印操作               \n"); 
    printf("\t     0. 退出操作               \n"); 
	printf("请输入相应操作: \n"); 
    scanf("%d",&chioce); 
    while(!(chioce>=0&&chioce<=4))   
	{             
		printf("输入有问题,请重新输入:"); 
		scanf("%d",&chioce); 
	} 
	while(chioce!=0)
	{                          
        switch(chioce)
		{ 
			case 1:  
				printf("请输入叶子节点的个数: \n");
				scanf("%d",&n);
				printf("请输入各个叶子节点所带有的权重:\n");
				for(i=0;i<n;i++)
					scanf("%d",&a[i]);
				root=CreateHuf(a,n);
				printf("已完成最优二叉树的构建过程!!!\n");
				break;
			case 2:   
				FILE *fp,*fp2;
				if((fp=fopen("123.txt","w+"))==NULL)
				{
					printf("文件创建错误,请检查错误后重新来过.\n");
					return ;
				}
				if((fp2=fopen("coding.txt","w+"))==NULL)
				{
					printf("文件创建错误,请检查错误后重新来过.\n");
					return ;
				}
                Hufcoding(root,0,fp,fp2);
				fclose(fp);
				fclose(fp2);
				printf("编码结果已写入123.txt文本文件中,请查看!!!\n");
				printf("编码结果已写入coding.txt文本文件中,请查看!!!\n");
                break;
			case 3:     
				Decoding_HuffumanTree(root,fp2);
				printf("\n译码结果已写入Decoding.txt文本文件中,请查看!!!\n");
                break; 
			case 4:    
				printf("以广义表形式打印哈夫曼树各叶子节点关系: \n");
				Print_BTree(root);
				printf("\n");
                break;  
        } 
        printf("请继续进行相应操作:"); 
        scanf("%d",&chioce); 
    } 
    return ; 
}

树状显示二叉树: 编写函数displaytree(二叉树的根指针,数据值宽度,屏幕的宽度)输出树的直观示意图。输出的二叉树是垂直打印的,同层的节点在同一行上。 [问题描述] 假设数据宽度datawidth=2,而屏幕宽度screenwidth为64=26,假设节点的输出位置用 (层号,须打印的空格数)来界定。 第0层:根在(0,32)处输出; 第1层:因为根节点缩进了32个空格,所以下一层的偏移量(offset)为32/2=16=screenwidth/22。即第一层的两个节点的位置为(1,32-offset),(1,32+offset)即(1,16),(1,48)。 第二层:第二层的偏移量offset为screenwidth/23。第二层的四个节点的位置 分别是(2,16-offset),(2,16+offset),(2,48-offset),(2,48+offset)即(2,8),(2,24),(2,40),(2,56)。 …… 第i层:第i层的偏移量offset为screenwidth/2i+1。第i层的每个节点的位置是访问第i-1层其双亲节点时确定的。假设其双亲的位置为(i-1,parentpos)。若其第i层的节点是其左孩子,那末左孩子的位置是(i,parentpos-offset),右孩子的位置是(i,parentpos+offset)。 [实现提示] 利用二叉树的层次遍历算法实现。利用两个队列Q,QI。队列Q中存放节点信息,队列QI中存相应于队列Q中的节点的位置信息,包括层号和需要打印节点值时需要打印的空格数。当节点被加入到Q时,相应的打印信息被存到QI中。二叉树本身采用二叉链表存储。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值