最近在做一个数据结构课程设计,希望大家给点帮助,欢迎讨论。

雪域迷影 2010-07-05 05:16:27

一下是我选择的数据结构课程设计:
老友记(friends)中使用频率最高的单词(堆排序、hash表)

电视剧《六人行》(Friends),又名《老友记》,是美国NBC电视台从1994年开播、连续播出了10年的一部幽默情景喜剧,也是美国历史上甚至是全球范围最成功、影响力最大的电视剧之一。《老友记》也是中国学生学习英语口语很好的题材。现在有一个疑问:《老友记》的一共十季的台词中哪一些单词使用频率最高呢?

输入:台词文件friends.txt(在Project7文件夹中)
输出:在此文件中找出出现次数最高的100个单词,并按照频率由高到低的顺序输出。格式如下:打印完一个单词之后空一格再打印该单词的频率。
例如:
I 23834
The 23139
To 17824
You 17583


提示:首先要对文件中的句子进行分词(把句子划分为若干个单词),存储到适当的数据结构中,(划分单词可以用空格作为依据)。 再统计每一个单词出现的频率,最后按照频率由大到小的顺序排序,并取前100个输出。

注意:在统计的时候有可能出现重复的单词,因为我们以空格作为划分单词的依据,所以两个单词the和The被认为是两个不同的单词,还有单词后边紧跟着标点符号也会影响单词的统计(No,和No.被认为是不同的单词,分别统计),这显然不是我们希望看到的结果。请想办法解决这个问题。

请教大家如何用某种数据结构保存大型文件中的数据并用堆排序、哈希表找出文件中使用频率最高的单词呢?


...全文
149 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
hlllhandsome 2010-07-25
  • 打赏
  • 举报
回复
#include "stdio.h"
#include "stdlib.h"
#include "memory.h"
#include "ctype.h"
#include "string.h"
#define FALSE 0
#define TRUE 1
typedef struct node
{
char name[20];
long count;
struct node *next;
}Node;

//移动函数(堆排序)
void move(Node *ht,int root,int bottom)
{
Node tmp = ht[root];
int value = tmp.count;
int i = root;
int j = 2*i;
int flag = FALSE;
while(j < bottom && !flag)
{
if(j < bottom && ht[j].count < ht[j+1].count)
j++;
if(value > ht[j].count)
flag = TRUE;
else
{
ht[i] = ht[j];
i = j;
j = 2*i;
}
}
ht[i] = tmp;
}
//建初堆
void heap_start(Node *ht,int length)
{
int len = length-1;
int i;
for(i = len/2;i >= 0;--i)
move(ht,i,len);
}
//堆排序
void Heap_Sort(Node *ht,int length)
{
int len = length-1;
int i;
Node tmp;
heap_start(ht,length);
for(i = len;i >= len - 100;--i)
{
tmp = ht[0];
ht[0] = ht[i];
ht[i] = tmp;
move(ht,0,i-1);
}
}

Node* Array( Node* m[], long *n )
{
int h=0,g=0,b,j = 0,i = 0;
Node *q = NULL,*p = NULL;
Node *a = ( Node* )malloc( *n * sizeof( Node ) + 10 );
for( i = 0; i < 26; i++ )
{
p = m[i]->next;
while( p )
{
strcpy( a[j++].name , p->name );
b = j - 1;
a[b].count = p->count;
p = p->next;
h++;
}

}
*n = j;
return a;
}



void CreateHX( char **word, long* number )
{
Node *p,*q;
Node *m[26];
int i,j = 0,k = 0;
long a = *number;
for( j = 0; j < 26; j++ )
{
m[j] = ( Node * )malloc( sizeof( Node ) );
if( !m[j])
{
printf("Malloc error!!");
return;
}
m[j]->next = NULL;
}
for( k = 0; k < a; k++)
{
if( !isupper( word[k][0] ) )//把小写字母改为大写
word[k][0] = toupper( word[k][0] );
i = word[k][0] - 65;//第一个字符按字母表的排序放在指定下标的数组中
q = m[i]->next;
while( q != NULL )
{
if( !strcmp( q->name, word[k] ) )
{
( q->count )++;
(*number)--;
break;
}
q = q->next;
}
if( !q )
{
p = ( Node * )malloc( sizeof( Node ) );
strcpy( p->name ,word[k]);
p->count = 1;
p->next = m[i]->next;
m[i]->next = p;
}

}
//Research( m, 100);
p = Array(m,number);
Heap_Sort(p,*number);
for(i = *number - 1;i > *number - 101;--i)
printf("\n单词:%s 次数:%d ",p[i].name,p[i].count);
}
//Node
void FileLength( FILE **pf,long *length )
{
if( ( *pf = fopen( "friends.txt", "rb" ) ) == NULL )
{
printf( "Open file error!!" );
exit(0);
}
if( !fseek( *pf, 0, SEEK_END ) )//fseek成功时返回0,否则返回-1
*length = ftell( *pf );
else
{
fclose( *pf );
printf( "fseek1 error!" );
return;
}
}
char* ReadFile( FILE *pf, long length )
{
char *buf;
/*把文件指针移到文件头*/
if(fseek( pf, 0, SEEK_SET ) )
{
fclose( pf );
printf( "fseek 2error!\n" );
return NULL;
}

if( buf = ( char * )malloc( sizeof( char ) * ( length + 1 ) ) )//加1是为了确保空间足够大
{
memset( buf, 0 , ( length + 1 ) );//清零
fread( buf, 1, length, pf );
fclose( pf );
}
else
{
fclose( pf );
printf( "malloc error!\n" );
return NULL;
}
return buf;
}

long countwords( char *buf, long length )
{
int i, sign = 1;
char ch;
long number = 0;
for(i = 0; i < length+1; i++)
{
ch = *( buf + i);
if((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'))
{
sign = 0;
}
else if( !sign )
{
number++;
sign = 1;
}
}
return number;
}
char** readwords( char *buf, long length, long* number)
{
char **word;
int i,k = 0,j = 0,sign = 1;
long num = 0;
//分配number(总单词个数)个长度为20(一般单词长度小于20)的字符数组
word = ( char ** )malloc( *number * sizeof( char* ) );

for( i = 0; i < (*number); i++ )
{
word[i] = ( char * )malloc( 20 * sizeof( char ) );
memset( word[i], 0, 20 );
}

for( i = 0; i < length; i++ )
{
if(buf[i] == '[')
while (buf[i]!=']')
{
i++;
}
else if( buf[i]=='(' )
while (buf[i]==')')
{
i++;
}
else if ( buf[i] == ':' )
for( i = i + 2; buf[i] != '\n'&&i < length; i++ )
{
if( ( buf[i] >= 'A' && buf[i] <='Z' ) || ( buf[i] >= 'a' && buf[i] <= 'z' ) )
{
word[k][j++] = buf[i];
sign = 0;
}
else if( !sign )
{
k++;
j = 0;
sign = 1;
num++;
}
}
}

*number = num;
return word;
}


int main()
{
char *buf, **word;
FILE *pf;
long num,number,length = 0;
FileLength( &pf, &length );

buf = ReadFile( pf, length );

number = countwords( buf, length );
num = number;
word = readwords( buf, length, &number);
printf("%d\n",number);
free( buf );
buf = NULL;

CreateHX( word, &number );
free(word);
word = NULL;
return 0;
}

自己好好看看吧!!!不算是好的代码。。。。。





雪域迷影 2010-07-14
  • 打赏
  • 举报
回复
我分开编译,麻烦看一下一下代码有什么问题,谢谢了!
VC6.0下
Header Files:
(1)hash.h
#ifndef hash_h
#define hash_h

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define hashnum 100000
#define INVALID 0//该结点中无数据
#define VALID 1//该结点中有数据


/*采用哈希表结点结构*/
typedef struct node

{
char str[50]; //存储单词,关键字
int position; //单词对应的ASCII编码值
int count; //用于记录单词的个数
int flag;//用来标识该结点中有无数据
struct node *next;
}CHashNode;

typedef struct Hash_Table{

CHashNode hash_table[hashnum];
int hashsize;//哈希表的实际表长
}CHashTable;

/* 初始化哈希表 */

void HashListInit(CHashTable*);


/* 在哈希表中查找元素 */

CHashNode* HashListSearch(CHashTable *HT,const char *str);



/* 在哈希表中插入元素 */

void HashListInsert(CHashTable *HT,const char *str);



int func(const char* str);//设计哈希函数

#endif

(2)Source Files
1)hash.cpp
#include"hash.h"
#include<string.h>


int func(const char* str)//设计哈希函数
{
int ret = 0;
while (*str!='\0')
ret += *(str++);//计算单词的ASCII编码值
return ret % hashnum;//除留取余法构造哈希函数
}


/* 初始化哈希表 */

void HashListInit(CHashTable* HT)
{

int i;
HT=(CHashTable*)calloc(hashnum,sizeof(CHashNode));
if(HT)
{
for(i=0;i<hashnum;i++)
{
HT->hashsize=0;
HT->hash_table[i].count=0;
strcpy(HT->hash_table[i].str, " ");
HT->hash_table[i].position=0;
HT->hash_table[i].next=NULL;
HT->hash_table[i].flag=INVALID;

}
}

}



/* 在哈希表中查找元素 */

CHashNode* HashListSearch(CHashTable *HT,const char *str)
{
int ret=func(str);
if(0==strcmp(HT->hash_table[ret].str,str))//无冲突,第一次即找到所要单词元素
return &(HT->hash_table[ret]);

CHashNode *index=&(HT->hash_table[ret]);//利用链地址法处理冲突,则用相应的方法查找冲突后的元素
while(index)
{
if(0==strcmp(index->str,str))
return index;
index=index->next ;
}

return NULL;//未找到则返回-1

}



/* 在哈希表中插入元素 */

void HashListInsert(CHashTable *HT,const char *str)//往哈希表中插入元素
{
int position=func(str);
CHashNode* nd;
CHashNode* index=&(HT->hash_table[position]);
if(INVALID==HT->hash_table[position].flag)//插入之前该位置无记录,即无冲突
{
strcpy(HT->hash_table[position].str,str);
HT->hash_table[position].count++;
HT->hash_table[position].position=position;
HT->hash_table[position].flag=VALID;
HT->hashsize++;
}
else//有冲突,采用链地址法解决冲突,分两种情况
{


if(0==strcmp(HT->hash_table[position].str,str))//所求哈希函数位置有单词与所插入单词相同
{
HT->hash_table[position].count++;


}
else//往冲突数组position位置后采用链地址法解决冲突
{




while(index->next!=NULL)
{
index=index->next;
if(0==strcmp(index->str,str))
{
index->count++;
break;
}
}

if(index->next==NULL)
{
nd== (CHashNode*)malloc(sizeof(CHashNode));

if(nd)
{
strcpy(nd->str,str);
nd->next = NULL;
index->next=nd;
nd->flag=VALID;
nd->position=position;
nd->count=1;
}





}






}




}




}


2)test.cpp
//#include"heap.h"
#include"hash.h"
#include <string.h>

#define MAX_size 1000000
int main()
{
FILE *fp;
//char filename[20];
CHashTable *HT;

int i;
int x;

char str[50];
char *p;
//char *q;


HashListInit(HT);

fp=freopen("text.txt","r",stdin);

while(scanf("%s",str)!=EOF)//每次从文件中读取一个字符串,去掉空格
{

x=1;


p =str;
//q=p;
while(*p)
{
if (!((*p >= 'a'&& *p <= 'z')||(*p >= 'A'&& *p <= 'Z')))
{
// *p='\0';
// str[0] = '\0';
x = 0;
break;
}
else
{

p++;
}


}

if(x == 1)//若读取的字符串为单词
{
printf("%s\n",p);
HashListInsert(HT,p);
}



printf("%s\n",str);
HashListInsert(HT,str);









}
fclose(stdin);

for(i=0;i<hashnum;i++)
{
printf("单词%s的频率为:%d\n",HT->hash_table[i].str,HT->hash_table[i].count);

}

fclose(fp);



return 0;

}

为什么我调试的时候,总是会出现Error:expression can't be evalualted!呢?
程序显示在调用HashListInsert(HT,p);的时候会出现问题,不知道问题出现在哪儿?













丈八涯 2010-07-06
  • 打赏
  • 举报
回复
英文常用单词一共有多少个,只要老友记不频繁制造新词,那么存储应该没什么问题。
至于原文的分词处理,可以分块处理,减少一次读入量。

33,010

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧