【C++】对文章分词,并对词频用不同排序方法排序,比较各排序算法效率

文章分词

  • 1.问题描述
  • 2.需求分析
  • 3.概要设计
    • 3.1 主程序流程
    • 3.2 函数调用关系
  • 4.主函数实现
    • 4.1 main.h
    • 4.2 main.cpp
  • 5. 函数实现
    • 5.1 processDic函数
    • 5.2 forwardMax函数
    • 5.3 countWordFreq函数
    • 5.4 quickResult函数
    • 5.5 bubbleResult函数
    • 5.7 insertResult函数
    • 5.8 mergeResult函数
    • 5.9 heapResult函数
  • 6. 使用说明
  • 7. 程序具体实现

1.问题描述

中文自然语言处理中,分词是对文本进行分析的最基础工作。现有一段文章,要求对文章进行分词并且对词按词频进行排序。

基本要求:

查找并下载中文词典,根据该词典,对给出的3年内政府工作报告等文章,统计该文本的词频,分析近3年政府工作报告中最高词频的变化。 用快速排序,冒泡排序两种方法对词频进行排序,并保存在不同的文件中。

提高要求:

在基本要求完成的基础上,用直接插入排序、用归并排序、堆排序对词频进行排序,给出效率对比结果,包括时间效率和空间效率,并保存在不同文件中。 分析不同词频情况下(例如正序、逆序、随机)上述几种排序算法的效率。

2.需求分析

软件的基本功能:

根据本地中文词典对给定的文章进行分词,并统计词频。用快速排序,冒泡排序对词频进行排序,并将排序结果保存在不同文件中。再用直接插入排序、归并排序、堆排序对词频进行排序,并对这五种排序算法的时间效率和空间效率进行比较,分析不同词频情况下排序算法的效率,将对比结果保存在不同文件中。

输入/输出形式:

用户可以通过文件进行操作。程序将输出分词结果、词频统计结果、排序结果以及排序算法的效率对比结果到不同文件中。

输入形式:

在“文章输入”文件中输入文章内容。

输出形式:

将分词结果、词频统计结果、排序结果以及排序算法的效率对比结果输出到不同文件中。
测试数据要求:用户可以输入包含大量文本的文章,以及具有不同词频情况的测试数据,用于测试排序算法的效率和准确性。

3.概要设计

3.1 主程序流程

主程序流程图

3.2 函数调用关系

函数调用关系

4.主函数实现

4.1 main.h

#include <iostream>
#include <string>
#include <unordered_map>
using namespace std;
#define ERROR cerr << "Open error !" << endl; exit(0);//词语结构
struct Word
{string word;   //词语int sum;       //频率
};extern int maxLen;     //单个词语最大长度
extern int totalWord;  //存储词语总个数
extern unordered_map<string, int> hashMap;   //存储词语和频率void processDic(string _inFile);
void forwardMax(string _inFile, string _outFile);
void countWordFreq(Word* arr, string _outFile);
void reversequickSort(Word* r, int low, int high);
void quickResult(Word* arr, string _outFile1, string _outFile2, string _outFile3);
void bubbleResult(Word* arr, string _outFile1, string _outFile2, string _outFile3);
void insertResult(Word* arr, string _outFile1, string _outFile2);
void mergeResult(Word* arr, string _outFile1, string _outFile2);
void heapResult(Word* arr, string _outFile1, string _outFile2);

4.2 main.cpp

#include "main.h"int maxLen = 0;
int totalWord = 0;
unordered_map<string, int> hashMap;int main()
{cout << "正在运行中..." << endl;processDic("中文词典.txt");forwardMax("文章输入.txt", "分词结果.txt");Word* arr = new Word[totalWord];countWordFreq(arr, "词频统计.txt");quickResult(arr, "快速排序结果.txt", "时间效率对比结果.txt", "空间效率对比结果.txt");bubbleResult(arr, "冒泡排序结果.txt", "时间效率对比结果.txt", "空间效率对比结果.txt");insertResult(arr, "时间效率对比结果.txt", "空间效率对比结果.txt");mergeResult(arr, "时间效率对比结果.txt", "空间效率对比结果.txt");heapResult(arr, "时间效率对比结果.txt", "空间效率对比结果.txt");system("cls");cout << "已完成!" << endl;delete[] arr;return 0;
}

5. 函数实现

5.1 processDic函数

用于处理词典,将词典词语存储在哈希表中,并统计词语的最大长度。

//过滤非中文字符
bool Check(string s)
{if (s[0] >= 0 && s[0] < 256){return false;}else{return true;}
}//处理词典
void processDic(string _inFile)
{ifstream inFile(_inFile);if (!inFile){ERROR;}string str;while (inFile >> str){if (Check(str)){if (str.size() > maxLen){maxLen = str.size();}hashMap[str] = 0;}	}inFile.close();inFile.clear();
}

5.2 forwardMax函数

用正向最大匹配算法对输入的文章进行分词,在查找过程中统计文章词语数量,便于动态申请数组空间,并统计词频,最后将分词结果保存在文件中。

//文章分词
//正向最大匹配算法
void forwardMax(string _inFile, string _outFile)
{ifstream inFile(_inFile);ofstream outFile(_outFile);if (!inFile || !outFile){ERROR;}ostringstream temp;temp << inFile.rdbuf();string textTmp = temp.str();int Begin = 0, End = textTmp.size();while (Begin < End){string str;int num;for (num = min(maxLen, (End - Begin)); num > 0; num--){str = textTmp.substr(Begin, num);if (hashMap.find(str) != hashMap.end()){if (hashMap[str] == 0){totalWord++;}outFile << str;Begin += num;hashMap[str]++;break;}}if (num == 0){outFile << textTmp.substr(Begin, 1);Begin += 1;}outFile << "/";}inFile.close();inFile.clear();outFile.close();outFile.clear();
}

5.3 countWordFreq函数

用于统计文章词频,并将统计结果保存在文件中。

//统计词频
void countWordFreq(Word* arr, string _outFile)
{ofstream outFile(_outFile);if (!outFile){ERROR;}int i = 0;for (unordered_map<string, int>::iterator it = hashMap.begin(); it != hashMap.end(); it++){if (it->second > 0){arr[i].word = it->first;arr[i].sum = it->second;i++;outFile << it->first << "\t\t出现次数:\t" << it->second << endl;}}outFile.close();outFile.clear();
}

5.4 quickResult函数

实现对随机词频、正序词频、逆序词频的快速排序,并将排序结果,排序时间、空间效率保存在不同文件中。

double quickMemory = 0;//快速排序
int Part(Word* r, int low, int high)
{int i = low, j = high;while (i < j){while (i < j && r[i].sum >= r[j].sum){j--;}if (i < j){swap(r[i], r[j]);i++;}while (i < j && r[i].sum >= r[j].sum){i++;}if (i < j){swap(r[i], r[j]);j--;}}quickMemory += sizeof(int) * 2;return i;
}void quickSort(Word* r, int low, int high)
{if (low < high){int pivot = Part(r, low, high);quickSort(r, low, pivot - 1);quickSort(r, pivot + 1, high);}quickMemory += sizeof(int);
}//快速排序结果
void quickResult(Word* arr, string _outFile1, string _outFile2, string _outFile3)
{Word* r = new Word[totalWord];clock_t start1, end1, start2, end2, start3, end3;copy(arr, arr + totalWord, r);ofstream outFile1(_outFile1);ofstream outFile2(_outFile2);ofstream outFile3(_outFile3);if (!outFile1 || !outFile2 || !outFile3){ERROR;}start1 = clock();quickSort(r, 0, totalWord - 1);end1 = clock();outFile3 << "排序方法\t\t所占内存大小\n\n";outFile3 << "快速排序\t\t" << quickMemory / 1024 << "KB" <<  endl << endl;	start2 = clock();quickSort(r, 0, totalWord - 1);end2 = clock();reversequickSort(r, 0, totalWord - 1);start3 = clock();quickSort(r, 0, totalWord - 1);end3 = clock();for (int i = 0; i < totalWord; i++){outFile1 << r[i].word << "\t\t出现次数:\t" << r[i].sum << endl;}outFile2 << "排序方法\t\t随机词频用时\t\t正序词频用时\t\t逆序词频用时\n\n";outFile2 << "快速排序\t\t" << double(end1 - start1) / CLOCKS_PER_SEC << "s\t\t\t"<< double(end2 - start2) / CLOCKS_PER_SEC << "s\t\t\t" << double(end3 - start3) / CLOCKS_PER_SEC << "s\n\n";delete[] r;outFile1.close();outFile1.clear();outFile2.close();outFile2.clear();outFile3.close();outFile3.clear();
}

5.5 bubbleResult函数

double bubbleMemory = 0;//冒泡排序
void bubbleSort(Word* r, int n)
{int exchange = n;while (exchange != 0){int bound = exchange;exchange = 0;for (int i = 1; i < bound; i++){if (r[i - 1].sum < r[i].sum){swap(r[i - 1], r[i]);exchange = i;}}}bubbleMemory += sizeof(int) * 3;
}//冒泡排序结果
void bubbleResult(Word* arr, string _outFile1, string _outFile2, string _outFile3)
{Word* r = new Word[totalWord];clock_t start1, end1, start2, end2, start3, end3;copy(arr, arr + totalWord, r);ofstream outFile1(_outFile1);ofstream outFile2(_outFile2, ofstream::app);ofstream outFile3(_outFile3, ofstream::app);if (!outFile1 || !outFile2 || !outFile3){ERROR;}start1 = clock();bubbleSort(r, totalWord);end1 = clock();outFile3 << "冒泡排序\t\t" << bubbleMemory / 1024 << "KB" <<  endl << endl;		start2 = clock();bubbleSort(r, totalWord);end2 = clock();reversequickSort(r, 0, totalWord - 1);start3 = clock();bubbleSort(r, totalWord);end3 = clock();for (int i = 0; i < totalWord; i++){outFile1 << r[i].word << "\t\t出现次数:\t" << r[i].sum << endl;}outFile2 << "冒泡排序\t\t" << double(end1 - start1) / CLOCKS_PER_SEC << "s\t\t\t"<< double(end2 - start2) / CLOCKS_PER_SEC << "s\t\t\t" << double(end3 - start3) / CLOCKS_PER_SEC << "s\n\n";delete[] r;outFile1.close();outFile1.clear();outFile2.close();outFile2.clear();outFile3.close();outFile3.clear();
}

5.7 insertResult函数

double insertMemory = 0;//直接插入排序
void insertSort(Word* r, int n)
{for (int i = 1; i < n; i++){Word temp = r[i];int j;for (j = i; j > 0 && r[j - 1].sum < temp.sum; j--){r[j] = r[j - 1];}r[j] = temp;}insertMemory += sizeof(int) * 2 + sizeof(Word);
}//直接插入排序结果
void insertResult(Word* arr, string _outFile1, string _outFile2)
{Word* r = new Word[totalWord];clock_t start1, end1, start2, end2, start3, end3;copy(arr, arr + totalWord, r);ofstream outFile1(_outFile1, ofstream::app);ofstream outFile2(_outFile2, ofstream::app);if (!outFile1 || !outFile2){ERROR;}start1 = clock();insertSort(r, totalWord);end1 = clock();outFile2 << "直接插入排序\t" << insertMemory / 1024 << "KB" <<  endl << endl;	start2 = clock();insertSort(r, totalWord);end2 = clock();reversequickSort(r, 0, totalWord - 1);start3 = clock();insertSort(r, totalWord);end3 = clock();outFile1 << "直接插入排序\t" << double(end1 - start1) / CLOCKS_PER_SEC << "s\t\t\t"<< double(end2 - start2) / CLOCKS_PER_SEC << "s\t\t\t" << double(end3 - start3) / CLOCKS_PER_SEC << "s\n\n";delete[] r;outFile1.close();outFile1.clear();outFile2.close();outFile2.clear();
}

5.8 mergeResult函数

double mergeMemory = sizeof(Word) * totalWord;//归并排序
void Merge(Word* a, Word* b, int low, int mid, int high)
{int i = low, j = mid + 1, k = 0;while (i <= mid && j <= high){if (a[i].sum >= a[j].sum){b[k++] = a[i++];}else{b[k++] = a[j++];}}while (i <= mid){b[k++] = a[i++];}while (j <= high){b[k++] = a[j++];}k = 0;for (int i = low; i <= high; i++){a[i] = b[k++];}mergeMemory +=  sizeof(int) * 3;
}void mergeSort(Word* r1, Word* r2, int low, int high)
{if (low < high){int mid = (low + high) / 2;mergeSort(r1, r2, low, mid);mergeSort(r1, r2, mid + 1, high);Merge(r1, r2, low, mid, high);}mergeMemory += sizeof(int);
}//归并排序结果
void mergeResult(Word* arr, string _outFile1, string _outFile2)
{Word* r1 = new Word[totalWord];Word* r2 = new Word[totalWord];clock_t start1, end1, start2, end2, start3, end3;copy(arr, arr + totalWord, r1);ofstream outFile1(_outFile1, ofstream::app);ofstream outFile2(_outFile2, ofstream::app);if (!outFile1 || !outFile2){ERROR;}start1 = clock();mergeSort(r1, r2, 0, totalWord - 1);end1 = clock();outFile2 << "归并排序\t\t" << mergeMemory / 1024 << "KB" <<  endl << endl;	start2 = clock();mergeSort(r1, r2, 0, totalWord - 1);end2 = clock();reversequickSort(r1, 0, totalWord - 1);start3 = clock();mergeSort(r1, r2, 0, totalWord - 1);end3 = clock();outFile1 << "归并排序\t\t" << double(end1 - start1) / CLOCKS_PER_SEC << "s\t\t\t"<< double(end2 - start2) / CLOCKS_PER_SEC << "s\t\t\t" << double(end3 - start3) / CLOCKS_PER_SEC << "s\n\n";delete[] r1;delete[] r2;outFile1.close();outFile1.clear();outFile2.close();outFile2.clear();
}

5.9 heapResult函数

double heapMemory = 0;//堆排序
void Sift(Word* r, int start, int end)
{int i = start, j = 2 * start + 1;while (j < end){if (j + 1 < end && r[j].sum > r[j + 1].sum){j++;}if (r[i].sum < r[j].sum){break;}else{swap(r[i], r[j]);i = j;j = i * 2 + 1;}}heapMemory += sizeof(int) * 2;
}void heapSort(Word* r, int n)
{for (int i = n / 2 - 1; i >= 0; i--){Sift(r, i, n);}for (int i = n - 1; i > 0; i--){swap(r[0], r[i]);Sift(r, 0, i);}heapMemory += sizeof(int);
}//堆排序结果
void heapResult(Word* arr, string _outFile1, string _outFile2)
{Word* r = new Word[totalWord];clock_t start1, end1, start2, end2, start3, end3;copy(arr, arr + totalWord, r);ofstream outFile1(_outFile1, ofstream::app);ofstream outFile2(_outFile2, ofstream::app);if (!outFile1 || !outFile2){ERROR;}start1 = clock();heapSort(r, totalWord);end1 = clock();outFile2 << "堆排序\t\t" << heapMemory / 1024 << "KB" <<  endl << endl;	start2 = clock();heapSort(r, totalWord);end2 = clock();reversequickSort(r, 0, totalWord - 1);start3 = clock();heapSort(r, totalWord);end3 = clock();outFile1 << "堆排序\t\t" << double(end1 - start1) / CLOCKS_PER_SEC << "s\t\t\t"<< double(end2 - start2) / CLOCKS_PER_SEC << "s\t\t\t" << double(end3 - start3) / CLOCKS_PER_SEC << "s\n\n";delete[] r;outFile1.close();outFile1.clear();outFile2.close();outFile2.clear();
}

6. 使用说明

在程序文件同一目录下的“文章输入.txt”中输入所要进行操作的文章。
运行程序,待控制台显示由“正在运行中…”转变成“已完成!”时,分词、统计、排序等操作便一并完成,并以文件形式保存在同一目录下,通过文件名称即可查看相应操作结果。

7. 程序具体实现

点击下方链接即可 ^ ^
此为链接,可查看/下载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/675222.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大模型系列之解读MoE

Mixtral 8x7B 的推出&#xff0c; 使我们开始更多地关注 基于MoE 的大模型架构&#xff0c; 那么&#xff0c;什么是MoE呢&#xff1f; 1. MoE溯源 MoE的概念起源于 1991 年的论文 Adaptive Mixture of Local Experts&#xff08;https://www.cs.toronto.edu/~hinton/absps/jjn…

【GDPU】数据结构实验十 哈夫曼编码

【实验内容】 1、假设用于通信的电文仅由8个字母 {a, b, c, d, e, f, g, h} 构成&#xff0c;它们在电文中出现的概率分别为{ 0.07, 0.19, 0.02, 0.06, 0.32, 0.03, 0.21, 0.10 }&#xff0c;试为这8个字母设计哈夫曼编码。 提示:包含两个过程:&#xff08;1&#xff09;构建…

C语言实现面向对象—以LED驱动为例

点亮一个LED 常见的LED代码 分层分离思想 面向对象的LED驱动 LED左边高电平。 当LED右边为低电平时&#xff0c;LED有电流通过&#xff0c;LED亮。反之&#xff0c;LED灭 GPIO功能描述&#xff1a; 点亮LED的步骤及代码&#xff1a; 开启GPIO的时钟 配置GPIO为输出模式 …

04-22 周日 阿里云-瑶光上部署FastBuild过程(配置TLS、自定义辅助命令)

04-22 周日 阿里云-瑶光上部署FastBuild过程 时间版本修改人描述2024年4月22日14:18:59V0.1宋全恒新建文档2024年4月23日20:41:26V1.0宋全恒完成了基本流程的添加 简介 前提 准备两台服务&#xff0c;一台部署Docker&#xff0c;一台部署FastBuild的镜像容器服务所述的Docke…

stm32f103zet6_DAC_2_输出电压

实现效果 DAC输出的电压 同过电压表测量电压 1.DAC配置的步骤 初始化DAC时钟。配置DAC的GPIO端口。设置DAC的工作模式&#xff08;例如&#xff0c;是否使用触发功能&#xff0c;是否启用DAC中断等&#xff09;。启动DAC。 2常用的函数 函数 HAL_DAC_Start() - 开启指定…

软件系统概要设计说明书(实际项目案例整理模板套用)

系统概要设计说明书 1.整体架构 2.功能架构 3.技术架构 4.运行环境设计 5.设计目标 6.接口设计 7.性能设计 8.运行设计 9.出错设计 全文档获取进主页 软件资料清单列表部分文档&#xff08;全套可获取&#xff09;&#xff1a; 工作安排任务书&#xff0c;可行性分析报告&…

阿里巴巴alibaba国际站API接口:商品详情和关键词搜索商品列表

阿里巴巴国际站&#xff08;Alibaba.com&#xff09;提供了API接口供开发者使用&#xff0c;以实现与平台的数据交互。然而&#xff0c;由于API的详细内容和调用方式可能会随着时间和平台更新而发生变化&#xff0c;以下是一个概述和一般性的指导&#xff0c;关于如何使用阿里巴…

如何让CANoe或Wireshark自动解析应用层协议

当我们使用CANoe软件或Wireshark工具抓取以太网总线上的报文时,网卡首先会把以太网总线上的模拟信号解析成以太网帧数据。数据链路层根据二层头部中的Type字段值确定上层的协议。 如果以太网使用的是TCP/IP协议栈,那么Type值要么是0x0800(IPv4),要么是0x0806(ARP),要么是0x…

USP技术提升大语言模型的零样本学习能力

大语言模型&#xff08;LLMs&#xff09;在零样本和少样本学习能力上取得了显著进展&#xff0c;这通常通过上下文学习&#xff08;in-context learning, ICL&#xff09;和提示&#xff08;prompting&#xff09;来实现。然而&#xff0c;零样本性能通常较弱&#xff0c;因为缺…

AndroidStudio的Iguana版的使用

1.AndroidStudio介绍 Android Studio 是用于开发 Android 应用的官方集成开发环境 (IDE)。Android Studio 基于 IntelliJ IDEA 强大的代码编辑器和开发者工具&#xff0c;还提供更多可提高 Android 应用构建效率的功能&#xff0c;例如&#xff1a; 基于 Gradle 的灵活构建系统…

YOLOv5 V7.0 - rknn模型的验证 输出精度(P)、召回率(R)、mAP50、mAP50-95

1.简介 RKNN官方没有提供YOLOv5模型的验证工具&#xff0c;而YOLOv5自带的验证工具只能验证pytorch、ONNX等常见格式的模型性能&#xff0c;无法运行rknn格式。考虑到YOLOv5模型转换为rknn会有一定的精度损失&#xff0c;但是需要具体数值才能进行评估&#xff0c;所以需要一个…

荷香堪筑梦,鸳鸯和月寻。(变相BFS搜索)

本题链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 题目&#xff1a; 样例&#xff1a; 输入 3 4 2 .... ***. ..a. 输出 yes 思路&#xff1a; 根据题意&#xff0c;这里 1 s 可以移动多次&#xff0c;我们将每次可以移动避开雪的的位置存储起来&#xff0c;判断当…