代码改变世界

第四次作业

2016-03-22 20:37  梁开宝  阅读(213)  评论(4编辑  收藏  举报

结对对象:郭自轻 微博地址:http://www.cnblogs.com/mengshen/ 贡献比例:50% /50%

基于作业3的结果,读取一个较小的文本文件A_Tale_of_Two_Cities.txt,统计该文件中的单词的频率,并将统计结果输出到当前目录下的 Result1.txt 文件。 (第一阶段初稿完成该要求)

  • 命令行格式: 提示符> Myapp.exe -f filename.txt > Result.txt (PS:C++ 程序,Java 程序输出方式类似) filename.txt 为前面下载的文件名。
  • 解释:
    • 选项 -f 表示后面跟文件名
    • 输出格式规定(参考作业3中的示例):
      • 首先按照频率由高到低排序
      • 频率一样的词, 按照字典顺序排序
  • 此外, 读取一个较大的文本文件Gone_with_the_wind.txt实验对比程序执行效率,做如下改进,比较改进前后程序执行时间。
  • 我的部分源程序:
  • typedef struct
    {
    char word[MAX_CHARACTER]; // 存储单词,不超过50个字符
    int count; // 单词出现次数
    } ElemType;
    typedef struct
    {
    ElemType *elem; // 存储空间基址
    int length; // 当前长度
    int listsize; // 当前分配的存储容量(以sizeof(ElemType)为单位)
    } SqList;
     
    // 线性表的初始化
    int SqListInit ( SqList *L )
    {
    // 构造一个空的线性表L
    L->elem = ( ElemType * ) malloc ( LIST_INIT_SIZE * sizeof ( ElemType ) );
     
    if ( !L->elem ) return OVERFLOW; // 存储分配失败
     
    L->length = 0;
    L->listsize = LIST_INIT_SIZE;
    return OK;
    }
     
    // 线性表的插入
    int SqListInsert ( SqList *L, int i, char *fword )
    {
    // 在顺序线性表L中第i个位置之前插入新的元素e
    // i的合法值为1≤i≤L.Length + 1
    if ( i < 0 || i > L->length )
    {
    printf ( "i的值不合法!" );
    return ERROR; // i的值不合法
    }
     
    if ( L->length >= L->listsize )
    {
    // 当前存储空间已满,增加分配
    ElemType *newbase = ( ElemType * ) realloc ( L->elem,
    ( L->listsize + LISTINCREMENT ) * sizeof ( ElemType ) );
     
    if ( !newbase )
    return OVERFLOW; // 存储分配失败
     
    L->elem = newbase; // 新基址
    L->listsize += LISTINCREMENT; // 增加存储容量
    }
     
    ElemType *p, *q;
    q = &L->elem[i];
     
    for ( p = &L->elem[L->length - 1]; p >= q; p-- ) // 插入位置之后元素逐个右移
    {
    * ( p + 1 ) = *p;
    }
     
    strcpy ( q->word, fword ); // 复制fword中的字符到L->elem[i-1].word中
    L->elem[i].count = 1; // 设置计数初值为1
    L->length++; // 表长增1
    return OK;
    }
     
    // 线性表二分法查找
    int SqListBSearch ( SqList *L, char *sword, int &i )
    {
    if ( L->length == 0 ) // 当线性表为空时
    {
    i = 0; // i返回单词插入位置
    return ERROR;
    }
     
    // 线性表不空时,在线性表L中查找元素sword,用i返回其在线性表中的位置
    int low = 0, high = L->length - 1, mid = L->length;
     
    while ( low <= high )
    {
    mid = ( low + high ) / 2;
    int k = strcmp ( L->elem[mid].word, sword );
     
    if ( k == 0 ) // 待查单词sword等于中间值,找到待查元素
    {
    i = mid;
    return OK; // 查找成功,函数返回值为1,用i返回所查元素在线性表中的位置
    }
    else if ( k > 0 ) // 待查单词sword小于中间值,继续在前半区间进行查找
    {
    high = mid - 1;
    i = low;
    }
    else // 待查单词sword大于中间值,继续在后半区间进行查找
    {
    low = mid + 1;
    i = high + 1;
    }
    }
     
    return ERROR; // 线性表中不存在待查元素,函数返回值为0,i返回单词插入位置
    }
     
    void SqListPrint ( FILE *f, char fname[], SqList *L )
    {
    fprintf ( f, "文档 %s 中总计有%d个单词\n", fname, L->length ); // 输出统计信息,L->length为单词个数
    fprintf ( f, "序号 单词 个数\n" );
     
    for ( int i = 0, j = 1 ; i < L->length ; i++, j++ ) // j-序号
    fprintf ( f, "%-5d %-20s %d\n", j, L->elem[i].word, L->elem[i].count );
    }
  • 运行结果:
  • 两个人一直琢磨着,好难啊,刚好两个人C++基础差,完成得很艰难,不过同学对我的帮助特别的大,很感谢他。github:https://github.com/liangkaibao/disicizuoye