基於線性表和二叉排序樹的低頻詞過濾系統

 

 

 

數據結構課程設計報告

 

基於線性表和二叉排序樹的低頻詞過濾系統

——採用的方法

 

 

 

 

 

班   級:        計算機軟件101        

姓   名:            **                  

指導教師:                                 

成   績:                                  

 

 

 

 

 

 

 

 

                               信息工程學院

 

                    2012  年  6  月  12  日

 

 


運行前,請在文件保存目錄下建立inFile.txt文件

inFile.txt

The importance of self-confidence Currently, self-confidence has been the order of the day. This does demonstrate the theory —— nothing is more valuable than self-confidence. It is clear that (self-confidence means trust in one's abilities). If you (are full of self-confidence, it will bring your creative power to play, arouse your enthusiasm for work, and help you overcome difficulties), as a result, your dreams will come true. On the contrary, if you (have no confidence in yourself, there is little possibility that you would ever achieve anything ). Failure will be following with you。It turns out that all your plan falls through. No one can deny another fact that (self-confidence gives you light when you are in dark and encouragement when you are dismayed).You don't have to look very far to find out the truth, in respect that we all know (the secret of MMe. Curie lies in perseverance and self-confidence, the latter in particular). It will exert a profound influence upon (the achievement of one's ambitions). With reference to my standpoint, I think (he that can have self-confidence can have what he will).

 

目  錄

 

1 前言·· 1

2需求分析··2

3概要設計(特殊功能)··2

4詳細設計··2

5源代碼及調試··3

6特殊問題解決方法··9

7使用說明及測試結果··10

8結論··10

9總結與體會··11

10參考文獻··12

 

               

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1 前言

1.1 課題簡介

課程設計題目名稱:

基於線性表和二叉排序樹的低頻詞過濾系統

課程設計目的:

通過《數據結構》課程的學習,將數據結構應用在具體的編程方面,更加了解課程所學習的內容及思維邏輯。

課程設計意義:

利用數據結構課程設計,瞭解學生對《數據結構》的理解和加強學生對數據結構方面的應用知識。希望今後學生好好利用數據結構的知識和思想,解決各方面的編程難題。

課程設計內容:

對於一篇給定的英文文章,分別利用線性表和二叉排序樹來實現單詞頻率的統計,實現低頻詞的過濾,並比較兩種方法的效率。

課程設計要求:

1. 讀取英文文章文件(InFile.txt),識別其中的單詞。

2. 分別利用線性表和二叉排序樹構建單詞的存儲結構。當識別出一個單詞後,若線性表或者二叉排序樹中沒有該單詞,則在適當的位置上添加該單詞;若該單詞已經被識別,則增加其出現的頻率。

3. 統計結束後,刪除出現頻率低於五次的單詞,並顯示該單詞和其出現頻率。

4.其餘單詞及其出現頻率按照從高到低的次序輸出到文件中(OutFile.txt),同時輸出用兩種方法完成該工作所用的時間。

5.計算查找表的ASL值,分析比較兩種方法的效率。

6.系統運行後主菜單(僅供參考)如下:

當選擇1後進入以下界面:

其中選擇2時顯示利用線性表來實現所有功能所用的時間。

當在主菜單選擇2二叉排序樹後,進入的界面與上圖類同。

 

1.2 方案及其論證

    語言:C

      運行環境:C-Free5.0

      可行性分析:建立單鏈表存儲InFile.txt英語文章單詞及頻率,建立二叉排序樹存儲InFile.txt英語文章單詞和頻率,分別實現單詞統計,刪除頻率低的單詞,輸出其餘單詞,並計算ASL值。

設計進度安排:

第一天

第二天

第三天

第四天

第五天

設計系統界面,查找資料

完成初步的程序設計

查資料解決調試中的問題

答疑,改進程序

驗收並完成報告

 

 

 

 

 

 

 

 

 

 

 

 

2需求分析

    建立單鏈表存儲InFile.txt英語文章單詞及頻率,建立二叉排序樹存儲InFile.txt英語文章單詞和頻率,分別實現單詞統計,刪除頻率低的單詞,用outFile.txt文本輸出其餘單詞,並計算ASL值。

根據第一個要求,系統實現是沒有問題的,簡單易行;第二個要求可以通過運算符號來實現,也是簡單易行的;第三個要求實現較爲困難,需要通過嚴密的思維邏輯一一實現完成,是本次編程的重難點。

 

3概要設計(特殊功能)

 

 

4詳細設計

 

5源代碼及調試

 

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<string.h>
#include <time.h>
typedef struct node1{		//單鏈表節點 
	char data[20];
	int count;
	struct node1 *next;
}LNode,*LinkList;
typedef struct node2//排序二叉樹節點 
{
	char data[20];
	int count;
	struct node2* left;
	struct node2* right;
}BSTNode, *BSTree;
BSTree T,nT;
typedef struct stack//非遞歸中序遍歷寫入文件outFile.txt 
{
	BSTree data[1000];
	int top;
}seqstack;
/***************************************************************************************///單鏈表 
void swap(LinkList x,LinkList y)
{
	char a[20];
	strcpy(a,x->data);
	int b=x->count;
	
	strcpy(x->data,y->data);
	x->count=y->count;
	
	strcpy(y->data,a);
	y->count=b;	
}
void sort_slist(LinkList &L)
{
	LinkList p,q,temp;
	p=L->next;
	while(p)
	{
		q=p->next;
		while(q)
		{
			if(p->count<q->count)
			{
				swap(p,q);
			}
			else 
				q=q->next;
		}
		p=p->next;
	}
}
void InitList(LinkList &L)
{
	L=(LinkList)malloc(sizeof(LNode));
	L->next=NULL;
}
int InsertList(LinkList &L,char *a)//先將每一元素存入線性鏈表中,然後統計個數 
{
	int flag=0;
	LinkList P;
	LinkList Q;
	Q=L->next;
	while(Q!=NULL)
	{
		if(!strcmp(a,Q->data))
		{
			Q->count++;
			flag=1;
			break;
		}
		Q=Q->next;
	}
	if(!flag)
	{
		P=(LinkList)malloc(sizeof(LNode));
		strcpy(P->data,a);
		P->count=1;
		P->next=L->next;
		L->next=P;
		
	}
}
int LNodeprint(LinkList &L)
{
	LinkList P;
	P=L->next;
	printf("單詞       個數統計\n"); 
	while(P!=NULL)
	{
		printf("%-10s    %d\n",P->data,P->count);
		P=P->next;
	} 
}
void fprint1(LinkList &L)
{	
	LinkList P;
	FILE *out;
	out=fopen("outFile.txt","a+");//建立輸出文件
	fprintf(out,"單鏈表刪除個數<5的單詞:\n");
	P=L->next;
	while(P)
	{
		fprintf(out,"%s (%d)\t",P->data,P->count);
		P=P->next;
	}
	fclose(out);
}
int single_distinguish_count1()
{
    FILE *in;
    char a[20],c;
    LinkList L;
    InitList(L);
    in=fopen("inFile.txt","r");//打開輸入文件
    while(!feof(in))//直到碰見文件結束符結束循環
    {
    	int i=0;
    	memset(a,0,sizeof(a));
		while((c=fgetc(in))!=EOF&&!(c==','||c=='.'||c=='!'||c=='?'||c==' '||c=='('||c==')'))
		{
			a[i++]=c;
		}
		if(a[0])
		InsertList(L,a);
    }
	sort_slist(L);
	LNodeprint(L);
    fclose(in);//關閉文件	
}
void deletenode(LinkList &L)
{
	LinkList P,Q;
	FILE *out;
	out=fopen("outFile.txt","w+");//建立輸出文件
	P=L->next;
	while(P&&P->count>=5)
	{
		P=P->next;
	}
	while(P)
	{
		Q=P;
		P=P->next;
		printf("刪除節點: %-10s  %d\n",Q->data,Q->count);
		free(Q);
	}
}
int single_delete1()
{
    FILE *in;
    int j=1;
    char a[20],c;
    LinkList L;
    InitList(L);
    in=fopen("inFile.txt","r");//打開輸入文件
    while(!feof(in))//直到碰見文件結束符結束循環
    {
    	int i=0;
    	memset(a,0,sizeof(a));
		while((c=fgetc(in))!=EOF&&!(c==','||c=='.'||c=='!'||c=='?'||c==' '||c=='('||c==')'))
		{
			a[i++]=c;
		}
		if(a[0])
		{
			InsertList(L,a);
		}		
    }
	sort_slist(L);	
	printf("刪除低頻詞彙\n");
	deletenode(L);
}
void outnode(LinkList &L)
{
	LinkList P,Q;
	FILE *out;
	out=fopen("outFile.txt","w+");//建立輸出文件
	P=L->next;
	printf("刪除低頻率單詞後\n單詞       個數統計\n"); 
	while(P&&P->count>=5)
	{
		printf("%-10s  %d\n",P->data,P->count);
		fprintf(out,"%s(%d)\t",P->data,P->count);
		P=P->next;
	}
	printf("寫入文件outFile.txt成功\n");	
}
void single_output1()
{
    FILE *in;
    int j=1;
    char a[20],c;
    LinkList L;
    InitList(L);
    in=fopen("inFile.txt","r");//打開輸入文件
    while(!feof(in))//直到碰見文件結束符結束循環
    {
    	int i=0;
    	memset(a,0,sizeof(a));
		while((c=fgetc(in))!=EOF&&!(c==','||c=='.'||c=='!'||c=='?'||c==' '||c=='('||c==')'))
		{
			a[i++]=c;
		}
		if(a[0])
		{
			InsertList(L,a);
		}		
    }
	sort_slist(L);
	outnode(L);
    fclose(in);//關閉文件
}
int sumNode(LinkList &L)
{
	int sum=0;
	LinkList p;
	p=L->next;
	while(p)
	{
		sum++;
		p=p->next;
	}
	return sum;
}
int single_ASL1()
{
    FILE *in;
    int sum;
    char a[20],c;
    LinkList L;
    InitList(L);
    in=fopen("inFile.txt","r");//打開輸入文件
    while(!feof(in))//直到碰見文件結束符結束循環
    {
    	int i=0;
    	memset(a,0,sizeof(a));
		while((c=fgetc(in))!=EOF&&!(c==','||c=='.'||c=='!'||c=='?'||c==' '||c=='('||c==')'))
		{
			a[i++]=c;
		}
		if(a[0])
		{
			InsertList(L,a);
		}		
    }
    sum=sumNode(L);
	printf("單詞總個數:%d\n",sum);
    fclose(in);//關閉文件
	printf("ASL = %.2f \n",double(3*(sum+1)/4.0));
}
int continue_to_finish1()
{
	single_distinguish_count1();
	single_delete1();
	single_output1();
	single_ASL1();
}
int show_time1()
{
	double star,finish;
	star=(double)clock();//獲取當前時間
	single_distinguish_count1();
	single_delete1();
	single_output1();
	single_ASL1();
	finish=(double)clock();//獲取結束時間
	printf("執行時間:%.2f ms\n",(finish-star));//得到的是運行for語句所用的時間,時間單位了毫秒	
}
/*******************************************************************************///排序二叉樹
void insertNode(BSTree &T,char *a)
{
	if (T==NULL)
	{
	   	T=(BSTree)malloc(sizeof(BSTNode));
	   	strcpy(T->data,a);
	   	T->left=NULL;
	   	T->right=NULL;
	   	T->count=1;
	}
	else
	{
	   	if(strcmp(a,T->data)<0)
	   	{
			insertNode(T->left,a);
	   	}
  		else if(strcmp(a,T->data)==0)
  		{
		  	T->count++;
		  }
	   	else
	   	{
	    	insertNode(T->right,a);
	   	}
	}
}
void printTree(BSTree T)//中序遍歷二叉排序樹,得到有序序列
{
	if(T)
	{
	   printTree(T->left);
	   printf("%-10s   %d\n",T->data,T->count);
	   printTree(T->right);
	}
}
void fprint2(BSTree T)
{
	FILE *out;
	seqstack S;
	S.top=-1;
	out=fopen("outFile.txt","a+");//建立輸出文件
	fprintf(out,"排序二叉樹刪除個數 < 5 的單詞:\n");
	while(T||S.top!=-1)
	{
		while(T)
		{
			S.top++;
			S.data[S.top]=T;
			T=T->left;
		}
		if(S.top>-1)
		{
			T=S.data[S.top];
			S.top--;
			fprintf(out,"%s (%d)\t",T->data,T->count);
			T=T->right;
		}
	}
	fclose(out);
}
int single_distinguish_count2()
{
    FILE *in;
    T=NULL;
    in=fopen("inFile.txt","r");//打開輸入文件
    char a[20],c;
    while(!feof(in))//直到碰見文件結束符結束循環
    {
    	int i=0;
    	memset(a,0,sizeof(a));
		while((c=fgetc(in))!=EOF&&!(c==','||c=='.'||c=='!'||c=='?'||c==' '||c=='('||c==')'))
		{
			a[i++]=c;
		}
		if(a[0])
		insertNode(T,a);
    }   
    printf("中序遍歷二叉排序樹\n");
    printf("單詞       個數統計\n"); 
    printTree(T);
}
BSTree insertTree(BSTree &nT,BSTree T)//中序遍歷二叉排序樹,得到有序序列
{
	if (nT==NULL)
	{
	   	nT=(BSTree)malloc(sizeof(BSTNode));
	   	strcpy(nT->data,T->data);
		nT->count=T->count;
	   	nT->left=NULL;
	   	nT->right=NULL;
	}
	else
	{
	   	if(strcmp(T->data,nT->data)<0)
	   	{
			insertTree(nT->left,T);
	   	}
	   	else
	   	{
	    	insertTree(nT->right,T);
	   	}
	}
	return nT;	
}
void newBSTree(BSTree T)//中序遍歷二叉排序樹,得到有序序列
{
	if(T)
	{
	   newBSTree(T->left);
	   if(T->count>=5)
	   {
   			insertTree(nT,T);
	   }	   
	   newBSTree(T->right);
	}
}
int single_delete2()
{
	printf("刪除<5的二叉排序樹中序遍歷:\n");
	nT=NULL;
	newBSTree(T);
	printf("單詞       個數統計\n"); 
	printTree(nT);
}
void single_output2()
{
	printf("單詞       個數統計\n"); 
	printTree(nT);
	printf("寫入文件outFile.txt成功\n");	
	fprint2(nT);
}
int calculateASL(BSTree T,int *s,int *j,int i) /*計算平均查找長度*/
{
	if(T)
	{ 
		i++; *s=*s+i; 
		if(calculateASL(T->left,s,j,i)) 
		{ 
			(*j)++; 
			if(calculateASL(T->right,s,j,i))
			{
				i--; return(1);
			}
		}
	} 
	else return(1);
}
int single_ASL2()
{
	int s=0,j=0,i=0;
	calculateASL(T,&s,&j,i);
	printf("ASL = %d / %d \n",s,j);
	
}
int continue_to_finish2()
{
	single_distinguish_count2();
	single_delete2();
	single_output2();
	single_ASL2();	
}
int show_time2()
{
	double star,finish;
	star=(double)clock();//獲取當前時間
	single_distinguish_count2();
	single_delete2();
	single_output2();
	single_ASL2();
	finish=(double)clock();//獲取結束時間
	printf("執行時間:%.2f ms\n",(finish-star));//得到的是運行for語句所用的時間,時間單位了毫秒	
}
/*******************************************************************************///菜單設置 
void print1()
{
	printf("★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\n");	
	printf("★                            主菜單                                          ★ \n");
	printf("★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\n\n");	
	printf("                         ☆ 1.線性表\n");
	printf("                         ☆ 2.二叉排序樹\n");
	printf("                         ☆ 3.退出系統\n");
	printf("請輸入你的選擇:"); 
}
void print2()
{
	printf("			☆ 1.連續執行至完畢\n");
	printf("			☆ 2.顯示執行時間\n");
	printf("			☆ 3.單步執行:識別並統計單詞\n");
	printf("			☆ 4.單步執行:刪除並顯示出現頻率低的單詞\n");
	printf("			☆ 5.單步執行:輸出其餘單詞及其頻率\n");
	printf("			☆ 6.單步執行:計算並輸出ASL\n");
	printf("			☆ 7.返回主菜單\n");
	printf("請輸入你的選擇:"); 	
}
int mainmenu();
int Link()
{
	printf("★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\n");	
	printf("★                            線性表選擇菜單                                  ★ \n");
	printf("★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\n\n");	
	print2();
	int n;	
	scanf("%d",&n);
	while(!(n==1||n==2||n==3||n==4||n==5||n==6||n==7))
	{
		printf("輸入有誤,請重新輸入\n");
		scanf("%d",&n);
	}
	system("cls");
	switch (n)
	{
		case 1:
			continue_to_finish1();
			Link();
			break;
		case 2:
			show_time1();
			Link();
			break;
		case 3:
			single_distinguish_count1();
			Link();
			break;
		case 4:
			single_delete1();
			Link();
			break;
		case 5:
			single_output1();
			Link();
			break;
		case 6:
			single_ASL1();
			Link();
			break;
		case 7:
			mainmenu();
			break;			
	}
}
int Tree()
{
	printf("★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\n");	
	printf("★                            二叉排序樹選擇菜單                              ★ \n");
	printf("★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\n\n");	
	print2();
	int n;	
	scanf("%d",&n);
	while(!(n==1||n==2||n==3||n==4||n==5||n==6||n==7))
	{
		printf("輸入有誤,請重新輸入\n");
		scanf("%d",&n);
	}
	system("cls");
	switch (n)
	{
		case 1:
			continue_to_finish2();
			Tree();
			break;
		case 2:
			show_time2();
			Tree();
			break;
		case 3:
			single_distinguish_count2();
			Tree();
			break;
		case 4:
			single_delete2();
			Tree();
			break;
		case 5:
			single_output2();
			Tree();
			break;
		case 6:
			single_ASL2();
			Tree();
			break;
		case 7:
			mainmenu();
			break;			
	}	
}
int mainmenu()
{
	print1();
	int n;
	scanf("%d",&n);
	while(!(n==1||n==2||n==3))
	{
		printf("輸入有誤,請重新輸入\n");
		scanf("%d",&n);
	}
	system("cls");
	switch (n)
	{
		case 1: 			
			Link();
			mainmenu();
			break;
		case 2: 
			Tree();
			mainmenu();
			break;
		case 3: 
			printf("退出系統\n");
			exit(0);
	} 	
} 
int main()
{
	mainmenu();
}

調試過程中曾遇到的錯誤:

 

 

 

6特殊問題解決方法

 

 

 

7使用說明及測試結果

 

 

8結論

 

 

9總結與體會

 

 

指導教師意見:

 

 

 

 

 

簽名:

日期:


 



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章