数据结构实验报告二

1.以二叉链表为存储结构,实现二叉树的创建、遍历

1)问题描述:在主程序中设计一个简单的菜单,分别调用相应的函数功能:

       1…建立树

       2…前序遍历树

       3…中序(非递归)遍历树

4…后序遍历树

       0…结束

2)实验要求:在程序中定义下述函数,并实现要求的函数功能: 

CreateTree():按从键盘输入的前序序列,创建树

    PreOrderTree():前序遍历树(递归)

    InOrderTree():中序(非递归)遍历树

    LaOrderTree(): 后序遍历树(递归)

3)注意问题:

   注意理解递归算法的执行步骤。

   注意字符类型数据在输入时的处理。

   重点理解如何利用栈结构实现非递归算法

#include<iostream>
#include<cstdlib>
using namespace std;
typedef struct BiTNode{
	int data;
	BiTNode* lchild,*rchild;
};
typedef BiTNode* BiTree;

int STree(BiTree r,int a,int b){
	int flag;
	if(r == NULL) return 0;
    if(r->data == a){
    	if(r->lchild == NULL){
    		r->lchild = (BiTNode*)malloc(sizeof(BiTNode));
    		r->lchild->data = b;
			r->lchild->lchild = NULL;
			r->lchild->rchild = NULL;
			return 1; 
		}
		else if(r->rchild == NULL){
			r->rchild = (BiTNode*)malloc(sizeof(BiTNode));
			r->rchild->data = b;
			r->rchild->lchild = NULL;
			r->rchild->rchild = NULL;
			return 1; 
		}
	}
	else{
		flag = STree(r->lchild,a,b);
	    if(flag != 1){
		    flag = STree(r->rchild,a,b);			
		}
	}
	return flag;
} 

int count = 1;
void PreOrderTree(BiTree root,int m){
	if(root == NULL) return;
	if(m != count){
	    printf("%d ",root->data);
		count++;		
	}
    else{
    	printf("%d\n",root->data);
	}
	PreOrderTree(root->lchild,m);
	PreOrderTree(root->rchild,m);
} 

int count1 = 1;
void InOrderTree(BiTree root,int m){
	BiTree p,stack[100];
	int top = 0;
	if(root == NULL) return;
	p = root;
	while(!(p == NULL && top == 0)){
		while(p != NULL){
			if(top<99){
				stack[top] = p;
				top++;
			}
			else{
				printf("栈溢出");
				return; 
			}
			p = p->lchild; 
		}
		if(top<=0) return;
		else{
			top--;
			p = stack[top];
	            if(m != count1){
	                printf("%d ",p->data);
		            count1++;		
	            }
                else{
    	            printf("%d\n",p->data);
	            }

			p = p->rchild;
		}
	} 
}

int count2 = 1;
void LaOrderTree(BiTree root,int m){	
	if(root == NULL) return;
	LaOrderTree(root->lchild,m);
	LaOrderTree(root->rchild,m);
	if(m != count2){
	    printf("%d ",root->data);
		count2++;		
	}
    else{
    	printf("%d\n",root->data);
	}
} 

int main(){
	int n,count=0,k,m;
	BiTree t;
	t = (BiTNode*)malloc(sizeof(BiTNode));
	cout<<"1...建立树"<<endl;
	cout<<"2...前序遍历树"<<endl;
	cout<<"3...中序(非递归)遍历树"<<endl;
	cout<<"4...后序遍历树"<<endl;
	cout<<"0...结束"<<endl; 
	while(1){
		scanf("%d",&k);
		if(k==1){
			printf("请建立树:\n"); 
			scanf("%d",&n);   //输入节点个数 
            m=n;
	        if(n!=0){
	        while(n-1){
	            int a,b;
	            scanf("%d%d",&a,&b);
	            if(count == 0){
	   	            t->data = a;
	   	            t->lchild = NULL;
	   	            t->rchild = NULL;
	   	            count++;
	            }
	            STree(t,a,b);
	            n--;
	        }
	        }
		}
		else if(k==2){
			printf("前序遍历树\n");
			PreOrderTree(t,m);	
			cout<<endl;
		} 
		else if(k==3){
			printf("中序遍历树\n");
			InOrderTree(t,m);
			cout<<endl;
		}
		else if(k==4){
			printf("后序遍历树\n");
			LaOrderTree(t,m);
			cout<<endl;
		}
		else if(k==0){
			break;
		}
	}
	return 0;
}

2.在二叉树中,P所指结点为二叉树中任一给定的结点,编写算法求从根结点到P所指结点之间的路径。

   实验要求:以二叉链表作为存储结构

   实验提示:采用非递归后序遍历二叉树,当后序遍历访问到P所指结点时,此时栈中所有结点均为P所指结点的祖先,由这些祖先便构成了一条从根结点到P所指结点之间的路径。

#include<iostream>
#include<cstdlib>
using namespace std;
typedef struct BiTNode{
	int data;
	BiTNode *lchild,*rchild;
};
typedef BiTNode *BiTree;
typedef struct{
	BiTree link;
	int flag;
}StackType;

void LaOrderTree(BiTree root,int p){   //后序遍历非递归实现 
	StackType stack[100];
	BiTree q;
	int top,sign;
	if(root == NULL) return;
	top = -1;
	q = root;
	while(!(q==NULL && top==-1)){
		if(q!=NULL){
			top++;
			stack[top].link = q;
			stack[top].flag = 1;
			q = q->lchild;
		}
		else{
			q = stack[top].link;
			sign = stack[top].flag;
			top--;
			if(sign==1){
				top++;
				stack[top].link = q;
				stack[top].flag = 2;
				q = q->rchild;
			}
			else{
	            char tmp[100];
                int i=0,length;
                if(q->data == p){
                    length = top+1;
                	tmp[i] = p;
                	while(top != -1){
						q = stack[top].link;
                		tmp[++i] = q->data;
                		top--;
					}
					cout<<endl; 
					cout<<"路径为:"<<endl;
					while(length>0){
						printf("%d ",tmp[length]);
						length--;
					}	
					printf("%d",tmp[0]);
					break;
				}
				q = NULL;
			}
		}
	}
} 

int STree(BiTree r,int a,int b){
	int flag;
	if(r == NULL) return 0;
    if(r->data == a){
    	if(r->lchild == NULL){
    		r->lchild = (BiTNode*)malloc(sizeof(BiTNode));
    		r->lchild->data = b;
			r->lchild->lchild = NULL;
			r->lchild->rchild = NULL;
			return 1; 
		}
		else if(r->rchild == NULL){
			r->rchild = (BiTNode*)malloc(sizeof(BiTNode));
			r->rchild->data = b;
			r->rchild->lchild = NULL;
			r->rchild->rchild = NULL;
			return 1; 
		}
	}
	else{
		flag = STree(r->lchild,a,b);
	    if(flag != 1){
		    flag = STree(r->rchild,a,b);			
		}
	}
	return flag;
} 

int main(){
	int n,count=0;
	BiTree t;
	t = (BiTNode*)malloc(sizeof(BiTNode));
	cout<<"请建立树:"<<endl; 
	scanf("%d",&n);
	int m=n;
	if(n!=0){
	while(n-1){
	    int a,b;
	    scanf("%d%d",&a,&b);
	    if(count == 0){
	   	    t->data = a;
	   	    t->lchild = NULL;
	   	    t->rchild = NULL;
	   	    count++;
	    }
	    STree(t,a,b);
	    n--;
	}
    }
	int p;
	scanf("%d",&p);
	LaOrderTree(t,p);
	return 0;
}

3.试编写按层次顺序遍历二叉树的算法

问题描述:编写按层次顺序遍历二叉树的算法

实验要求:以二叉链表作为存储结构

#include<iostream>
#include<cstdlib>
using namespace std;
typedef struct BiTNode{
	int data;
	BiTNode *lchild,*rchild;
};
typedef BiTNode* BiTree; 

int STree(BiTree r,int a,int b){
	int flag;
	if(r == NULL) return 0;
    if(r->data == a){
    	if(r->lchild == NULL){
    		r->lchild = (BiTNode*)malloc(sizeof(BiTNode));
    		r->lchild->data = b;
			r->lchild->lchild = NULL;
			r->lchild->rchild = NULL;
			return 1; 
		}
		else if(r->rchild == NULL){
			r->rchild = (BiTNode*)malloc(sizeof(BiTNode));
			r->rchild->data = b;
			r->rchild->lchild = NULL;
			r->rchild->rchild = NULL;
			return 1; 
		}
	}
	else{
		flag = STree(r->lchild,a,b);
	    if(flag != 1){
		    flag = STree(r->rchild,a,b);			
		}
	}
	return flag;
} 

int count=1;
int print_level(BiTree T,int level,int k){
	if(!T || level < 0) return 0;
	if(level == 0){
		if(count!=k){
			cout<<T->data<<" ";
			count++;
		}
		else{
			cout<<T->data; 
		}
		return 1;
	}
	return print_level(T->lchild,level-1,k)+print_level(T->rchild,level-1,k);
}

void print_for_level(BiTree T,int m){
	int i=0;
	for(i=0; ;i++){
		if(!print_level(T,i,m)) break;
	}
}

int main(){
	int n,count=0;
	BiTree t;
	t = (BiTNode*)malloc(sizeof(BiTNode));
	cout<<"请建立树:"<<endl; 
	scanf("%d",&n);
	int m=n;
	if(n!=0){
	while(n-1){
	    int a,b;
	    scanf("%d%d",&a,&b);
	    if(count == 0){
	   	    t->data = a;
	   	    t->lchild = NULL;
	   	    t->rchild = NULL;
	   	    count++;
	    }
	    STree(t,a,b);
	    n--;
	}
	}
	cout<<endl;
	cout<<"按层次遍历结果为"<<endl; 
	print_for_level(t,m);
	return 0;
}

4.编写算法求二叉树高度及宽度。

1) 问题描述:二叉树高度是指树中所有节点的最大层数,二叉树宽度是指在二叉树的各层上,具有节点数最多的那一层上的节点总数。

2) 实验要求:以二叉链表作为存储结构

#include<iostream>
#include<cstdlib>
using namespace std;
typedef struct BiTNode{
	char data;
	BiTNode *lchild,*rchild;
};
typedef BiTNode *BiTree;

int STree(BiTree r,int a,int b){
	int flag;
	if(r == NULL) return 0;
    if(r->data == a){
    	if(r->lchild == NULL){
    		r->lchild = (BiTNode*)malloc(sizeof(BiTNode));
    		r->lchild->data = b;
			r->lchild->lchild = NULL;
			r->lchild->rchild = NULL;
			return 1; 
		}
		else if(r->rchild == NULL){
			r->rchild = (BiTNode*)malloc(sizeof(BiTNode));
			r->rchild->data = b;
			r->rchild->lchild = NULL;
			r->rchild->rchild = NULL;
			return 1; 
		}
	}
	else{
		flag = STree(r->lchild,a,b);
	    if(flag != 1){
		    flag = STree(r->rchild,a,b);			
		}
	}
	return flag;
} 

int Depth(BiTree T){
	int dep1,dep2;
	if(T == NULL) return 0;
	else{
		dep1 = Depth(T->lchild);
		dep2 = Depth(T->rchild);
		if(dep1>dep2) return(dep1 + 1);
		else return(dep2+1);
	}
} 

int Width(BiTree T){
	BiTree q[100];
	int front = -1, rear = -1;
	int flag = 0,count = 0,p;
	if(T!=NULL){
		rear++;
		q[rear] = T;   //入栈 
		flag=1;
		p=rear;
	}
	while(front<p){
		front++;
		T=q[front];
		if(T->lchild!=NULL){
			rear++;
			q[rear]=T->lchild;
			count++;
		}
		if(T->rchild!=NULL){
			rear++;
			q[rear]=T->rchild;
			count++;
		}
		if(front==p){
			if(flag<count) flag=count;
			count=0;
			p=rear;
		}
	} 
	return flag;
}
int main(){
	int n,count=0;
	BiTree t;
	t = (BiTNode*)malloc(sizeof(BiTNode));
	cout<<"请建立树:"<<endl;
	 
	scanf("%d",&n);
	int m=n;
	if(n!=0){
	while(n-1){
	    int a,b;
	    scanf("%d%d",&a,&b);
	    if(count == 0){
	   	    t->data = a;
	   	    t->lchild = NULL;
	   	    t->rchild = NULL;
	   	    count++;
	    }
	    STree(t,a,b);
	    n--;
	}
	}
	printf("深度为:%d 宽度为:%d",Depth(t),Width(t));
	return 0;
}

5.实现一个哈夫曼编/译码系统

1)问题描述:利用哈夫曼编码进行信息通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传输数据预先编码,在接收端将传来的数据进行译码。对于双工信道,每端都需要一个完整的编码/译码系统。试为这样的信息收发站写一个哈夫曼的编/译码系统。

 

2)实验要求:一个完整的系统应具有以下功能:

(1) I:初始化(Initialization)。从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件hfmTree中。

(2) E:编码(Encoding)。利用已建好的哈夫曼树对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。

(3) D:译码(Decoding)。利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件TextFile中。

(4) P:打印代码文件(Print)。将文件CodeFile以紧凑格式显示在终端上,每行50个代码。同时将此字符形式的编码文件写入文件CodePrin中。

(5) T:打印哈夫曼树(Tree printing)。将已在内存中的哈夫曼树以直观的方式显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint中。

3) 实现提示:

(1) 文件CodeFile的基类型可以设为字节型。

(2) 用户界面可以设计为“菜单”方式:显示上述功能符号,再加上“Q”,表示退出运行Quit。请用户键入一个选择功能符。此功能执行完毕后再显示此菜单,直至某次用户选择了“E”为止。

(3) 在程序的一次执行过程中,第一次执行I、D或C命令之后,哈夫曼树已经在内存了,不必再读入。每次执行中不一定执行I命令,因为文件hfmTree可能早已建好。

#include<iostream>
using namespace std;
#include<cstdlib>
#include<cstring>
#include<cmath>
#define MaxWeight 1000
#define MaxLeaf 300
#define MaxNode MaxLeaf*2-1
#define MaxBit 100
typedef struct HNodeType{
	int weight;
	int parent;
	int lchild;
	int rchild;
	char ch;
}; 
typedef struct HCodeType{
	int bit[MaxBit];
	int start;
};
typedef struct{
	HNodeType link;
	int flag;
}StackType;
int N;
void HuffmanTree(HNodeType HuTree[],int n){     //哈弗曼树的构造 
	FILE *fp;
	int i,j,m1,m2,x1,x2;
//	scanf("%d",&n);        //输入字符集大小
	for(i=0;i<2*n-1;i++){
		HuTree[i].weight = 0;
		HuTree[i].parent = -1;
		HuTree[i].lchild = -1;
		HuTree[i].rchild = -1;
		HuTree[i].ch = '$'; 
	}
	getchar();	
	for(i=0;i<n;i++){
		scanf("%c",&HuTree[i].ch); 
		getchar(); 
	}
	for(i=0;i<n;i++){
		scanf("%d",&HuTree[i].weight);
	}
	for(i=0;i<n-1;i++){
		m1 = m2 = MaxWeight;
		x1 = x2 = 0;
		for(j=0;j<n+i;j++){
			if(HuTree[j].weight<m1 && HuTree[j].parent == -1){
				m2 = m1;
				x2 = x1;
				m1 = HuTree[j].weight;
				x1 = j;
			}
			else if(HuTree[j].weight<m2 && HuTree[j].parent == -1){
				m2 = HuTree[j].weight;
				x2 = j;
			}
		}
		HuTree[x1].parent = n+i;
		HuTree[x2].parent = n+i;
		HuTree[n+i].weight = HuTree[x1].weight + HuTree[x2].weight;
		HuTree[n+i].lchild = x1;
		HuTree[n+i].rchild = x2;
	}
	fp=fopen("hfmTree.dat","wb");
	for(i=0;i<2*n-1;++i)
		fwrite(&HuTree[i],sizeof(HuTree),1,fp);  
		//在hfmTree中存入树的各节点数据域信息 
	fclose(fp);
}
//编码
void HaffmanCode(HNodeType HuTree[],int n){
	
	HCodeType HuffCode[MaxNode],cd;
	int i,j,c,p;
//	HuffmanTree(HuTree,n);
	for(i=0;i<n;i++){
		cd.start = n-1;
		c = i;
		p = HuTree[c].parent;
		while(p!=-1){
			if(HuTree[p].lchild==c) cd.bit[cd.start]=0;
			else cd.bit[cd.start]=1;
			cd.start--;
			c = p;
			p = HuTree[c].parent;
		}
		for(j=cd.start+1;j<n;j++){
			HuffCode[i].bit[j] = cd.bit[j];
		}
		HuffCode[i].start = cd.start;
	}	
	//输出编码 
	FILE *fp1;
	fp1 = fopen("ToBeTran.txt","r");
	FILE *fp2;
    fp2=fopen("CodeFile.txt","w");
    char b[100];
    int f=0;
	while(fscanf(fp1,"%c",&b[f]) && !feof(fp1)){
		i=0;
		while(i<n){
			if(b[f] == HuTree[i].ch){
				for(j=HuffCode[i].start+1;j<n;j++){
			        fprintf(fp2,"%ld",HuffCode[i].bit[j]);
    		    }
    		    break;
			}
			else{
				i++;
			}
		}
		f++;
	}
	fclose(fp1);
	fclose(fp2);
} 

int main(){
	HNodeType HuTree[100];
	int Q,n;
	char T;
	int p=0,c;
	char b;
    cout<<"I:初始化"<<endl;
    cout<<"E:编码"<<endl;
    cout<<"D:译码"<<endl;
    cout<<"P:打印代码文件"<<endl;
    cout<<"T:打印哈弗曼树"<<endl;
    cout<<"Q:退出"<<endl;	
    cout<<endl; 
	cout<<"请首先建立树:"<<endl;
	scanf("%c",&T);	

	while(T != 'Q'){
		if(T=='I'){
		
			cout<<"格式为:节点个数 各节点名称 各节点权值"<<endl; 
			scanf("%d",&n);
			HuffmanTree(HuTree,n);
			cout<<"建立哈弗曼树成功!"<<endl;
			cout<<endl;
		}
		else if(T=='E'){
			HaffmanCode(HuTree,n);
			cout<<"编码成功!"<<endl;
			cout<<endl;
		}
		else if(T=='D'){
			FILE *fp4;
	        fp4 = fopen("CodeFile.txt","r");
			FILE *fp5;
	        fp5 = fopen("TextFile.txt","w"); 
			getchar();
			while(p != -1){
				c=p;
				p = HuTree[c].parent;
			}
			int q=c;
            int count=0;
            int d=0;
			    string str;
            while(fscanf(fp4,"%c",&str[d]) && !feof(fp4)){
				if(str[d] == '0'){
					q = HuTree[q].lchild;
					if(HuTree[q].ch != '$'){
                        fprintf(fp5,"%c",HuTree[q].ch);
						q = c;
					}
				}
				else if(str[d] == '1'){
					q = HuTree[q].rchild;
					if(HuTree[q].ch != '$'){
						fprintf(fp5,"%c",HuTree[q].ch);
						q = c;	
					}
				}
				d++;
	    	}    
			cout<<"译码成功!"<<endl;
			cout<<endl;
		}
		
		else if(T == 'P'){
            FILE *fp8,*fp6;
            int num=100;
            char a[num];
            fp8=fopen("CodeFile.txt","r"); 
            fp6=fopen("CodePrin.txt","w"); 
            fgets(a,num,fp8);
            cout<<"打印CodeFile文件:"<<endl;
            int l= strlen(a);
            for(int j=0;j<l;j++)
            {
                cout<<a[j];
                fprintf(fp6,"%c",a[j]);
                if((j+1)%50==0)       //每行输出50个 
                    cout<<endl;
            }
            cout<<endl;
            fclose(fp8);
            cout<<"输出成功!"<<endl;
			cout<<endl;
		}
		else if(T == 'T'){
			FILE *fp7;
			fp7 = fopen("TreePrint.txt","w");
			int i=2*n-2,j=i+2,count=0,sum=0;
			int k=1;sum = pow(2,0);
			cout<<"哈弗曼树为:"<<endl; 
			while(j--){
		    	cout<<" ";
		    	fprintf(fp7,"%c",' ');
			}
		    while(i>=0){
		    	j=i;
		    	count++;
		    	cout<<HuTree[i].weight<<" "; 
		    	fprintf(fp7,"%d",HuTree[i].weight);
		    	fprintf(fp7,"%c",' ');
		    	if(count == sum){
		    		sum += pow(2,k);
		    		k++;
					cout<<endl;
					cout<<endl;
				    while(j--){
		    	    	cout<<" ";
		    	    	fprintf(fp7,"%c",' ');
				    }
				} 
				i--;
			}
			cout<<endl; 
			cout<<endl; 
			cout<<endl; 
		}
		scanf("%c",&T);
	} 
	cout<<"结束"<<endl; 
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41106517/article/details/94717909