#include <iostream>
#include <fstream>
#include <time.h>
#include <cstring>
#include <string.h>
#include <windows.h>
using namespace std;
#define MAX 99
//二叉排序树的存储定义
typedef struct BiNode {
string WordName; //单词名称
int count; //单词出现频率
struct BiNode* lchild;
struct BiNode* rchild;
} BSTNode, * BSTree;
//线性表的存储定义
typedef struct LNode {
string WordName;
int count;
LNode* next;
}LNode, *LinkList;
//***************************************************************单链表
class Linear{
private:
LNode* first;
public:
//链表的创建 构造函数
Linear() {
first = new LNode();
first->next = NULL;
}
//线性表添加单词
void LinearAdd(string tempWord);
//读取文件
void LinearRead();
//删除频率低于5的单词
void LinearDelete();
//高频写入文件
void LinearWrite();
//线性表
void LinearTable();
//计算ASL
void FindASL();
};
//************************************************************二叉排序树
//
class BiSortTree {
private:
BiNode* root;
public:
//二叉树的创建 构造函数
BiSortTree() {
root = new BiNode();
root = NULL;
}
//返回根节点 方便遍历
BiNode* GetRoot() {
return root;
cout << "GetRoot函数" << endl;
}
//二叉树添加单词
BiNode* InsertBST(BiNode* root,BiNode *s);
//读取文件
BiNode* ReadBST();
//删除二叉树的某一个结点
void NextRep(BiNode* p);
//删除频率低于5的单词
void DeleteBST(BiNode* root);
//右中左遍历
void GetInBST(BiNode* root);
//完成写入文件
void WriteBST(BiNode* root);
//二叉排序树
void TableBST();
//计算ASL
void FindASL();
};
//主菜单
void Menu1() {
cout << "1、线性表" << endl;
cout << "2、二叉排序树" << endl;
cout << "3、退出系统" << endl;
cout << "请选择你需要的服务,输入数字(1~3):" << endl;
}
//菜单二
void Menu2() {
cout << "1、连续执行至完毕" << endl;
cout << "2、显示执行时间" << endl;
cout << "3、单步执行:识别并统计单词" << endl;
cout << "4、单步执行:删除并显示低频词汇" << endl;
cout << "5、单步执行:输出其余单词及其频率" << endl;
cout << "6、单步执行:计算并输出ASL值" << endl;
cout << "7、返回主菜单" << endl;
cout << "请选择你需要的服务,输入数字(1~7):" << endl;
}
void Main(int op, int op1) {
if (op == 1) {
Linear lin;
if (op1 == 1)lin.LinearTable();
else {
while (op1 < 7 && op1 >0) {
switch (op1) {
case 1:
lin.LinearTable();
break;
case 2: {
clock_t start = clock();
lin.LinearTable();
clock_t End = clock();
cout << "All Time :" << (double)End - (double)start / CLK_TCK << endl;
break;
}
case 3:
lin.LinearRead();
break;
case 4:
lin.LinearDelete();
break;
case 5:
lin.LinearWrite();
break;
case 6:
lin.FindASL();
break;
}//stwich
cout << "继续执行请输入(1~6)" << endl;
cin >> op1;
while (op1 < 1 || op1>6) {
cout << "选择有误,请重新选择!" << endl;
cin >> op1;
}
}//while
}//else
}//if1
else {
BiSortTree bst;
if (op1 == 1)bst.TableBST();
else {
while (op1 < 7 && op1 >0) {
switch (op1) {
case 1:
bst.TableBST();
break;
case 2: {
clock_t start = clock();
bst.TableBST();
clock_t End = clock();
cout << endl;
cout << "All Time :" << (double)End - (double)start / CLK_TCK << endl;
break;
}
case 3: {
bst.ReadBST();
break;
}
case 4:
bst.DeleteBST(bst.GetRoot());
break;
case 5:
bst.WriteBST(bst.GetRoot());
break;
case 6:
break;
}//switch
cout << "继续执行请输入(1~6)" << endl;
cin >> op1;
while (op1 < 1 || op1>6) {
cout << "选择有误,请重新选择!" << endl;
cin >> op1;
}
}//while1
}//else2
}//else1
system("pause");
}
//主函数
int main(){
bool tag = true;
int op,op1;
while (tag) {
system("cls");//清屏
Menu1();
cin >> op;
while (!(op == 1 || op == 3 || op == 2)) {
cout << "选择有误,请重新选择!" << endl;
cin >> op;
}
if (op == 3) {//退出系统
tag = false;
continue;
}
system("cls");//清屏
Menu2();
cin >> op1;
while (op1 < 1 || op1>7) {
cout << "选择有误,请重新选择!" << endl;
cin >> op1;
}
if (op1 == 7) continue;
Main(op, op1);
}
return 0;
}
//--------------------------------------------//线性表类成员的定义
//线性表添加单词
void Linear::LinearAdd(string tempWord) {
LNode* p = first, * r;
while (p != NULL && p->WordName != tempWord) {
p = p->next;
if (p && p->WordName == tempWord) { //找到频率加1
(p->count)++;
return;
}
}
//找不到添加
r = new LNode();
r->WordName = tempWord;
r->count = 1;
r->next = first->next;
first->next = r;
}
//读取文件
void Linear::LinearRead() {
//打开文件
fstream in;
in.open("Infile.txt", ios::in);
if (!in.is_open()) {//判断文件是否能打开
cout << "读取文件失败" << endl;
}
//读取字符和添加
string tempWord;
while (in >> tempWord) {
if (tempWord.at(tempWord.length() - 1) < 65 || tempWord.at(tempWord.length() - 1) == '"')//判断单词尾部是否是符号
tempWord.erase(tempWord.length() - 1);
if (tempWord.at(0) == '"') //去头
tempWord = tempWord.substr(1, tempWord.length());
LinearAdd(tempWord);//添加
}
in.close();//关闭文件
}
//删除频率低于5的单词
void Linear::LinearDelete() {
LNode* p = first->next, * s = first;
cout << "低频词汇及其频率" << endl;
while (p) {//结束条件
if (p->count < 5) { //小于5删除
cout << p->WordName << ' ' << p->count << endl;
s->next = p->next;
p = s->next;
}
else {//没有删除的情况下
p = p->next;//移动
s = s->next;
}
}
}
//高频写入文件
void Linear::LinearWrite() {
fstream out;
out.open("Ontfile.txt", ios::out);
if (!out.is_open()) {//判断文件是否能打开
cout << "读取文件失败" << endl;
}
int max = 0;
LNode* p = first;
while (p) { //找出最大频率
if (p->count > max)
max = p->count;
p = p->next;
}
//按照频率从高到低写入
for (int i = max; i >= 5; i--) {
p = first;
while (p) {
if (p->count == i)
out << p->WordName << ' ';
p = p->next;
}
}
}
//线性表
void Linear::LinearTable() {
//添加单词
LinearRead();
//删除低频词汇
LinearDelete();
//从高到低写入文件
LinearWrite();
//计算ASL
FindASL();
}
//平均查找长度
void Linear::FindASL() {
LNode* p = first;
int length = 0;
while (p) {
length++;
p = p->next;
}
cout << "平均查找长度为:" << length / 2.0 << endl;
}
//--------------------------------------------------------//排序二叉树
//二叉树添加单词
BiNode* BiSortTree::InsertBST(BiNode* root, BiNode* s) {
if (root == NULL)
return s;
else
if (s->WordName == root->WordName)//相等++
(root->count)++;
else if (s->WordName < root->WordName) //递归寻找
root->lchild = InsertBST(root->lchild, s);
else
root->rchild = InsertBST(root->rchild, s);
return root;
}
//读取文件
BiNode* BiSortTree::ReadBST() {
//打开文件
fstream in;
in.open("Infile.txt", ios::in);
if (!in.is_open()) {//判断文件是否能打开
cout << "读取文件失败" << endl;
}
//读取字符和添加
string tempWord;
BiNode* s;
while (in >> tempWord) {
if (tempWord.at(tempWord.length() - 1) < 65 || tempWord.at(tempWord.length() - 1) == '"')//判断单词尾部是否是符号
tempWord.erase(tempWord.length() - 1);
if (tempWord.at(0) == '"') //去头
tempWord = tempWord.substr(1, tempWord.length());
s = new BiNode();
s->WordName = tempWord;
root = InsertBST(root, s);//添加
}
in.close();//关闭文件
return root; //返回根节点
}
//删除某一节点p
void BiSortTree::NextRep(BiNode* p) {
cout << p->WordName << ' ' << p->count + 1 << endl;
//从二叉排序树T中删除关键字等于key的结点
BiNode* k = GetRoot();
BiNode* f = NULL; //初始化
BiNode* q, * s;
/*------------下面的while循环从根开始查找关键字等于key的结点*k-------------*/
//找要是找父亲结点 便于后面根的删除
while (k) {
if (k->WordName == p->WordName)
break; //找到关键字等于key的结点*p,结束循环
f = k; //*f为*p的双亲结点
if (k->WordName > p->WordName)
k = k->lchild; //在*p的左子树中继续查找
else
k = k->rchild; //在*p的右子树中继续查找
}//while
if (!p) {//这个没有必要写 但是我的技术太菜了 我怕空指针
cout << "待删除的元素不存在!" << endl;
return; //找不到被删结点则返回
}
/*―考虑三种情况实现p所指子树内部的处理:*p左右子树均不空、无右子树、无左子树―*/
if ((p->lchild) && (p->rchild)) { //被删结点*p左右子树均不空
q = p;
s = p->lchild;
while (s->rchild) { //在*p的左子树中继续查找其前驱结点,即最右下结点
q = s;
s = s->rchild;
} //向右到尽头
p->WordName = s->WordName;//s指向被删结点的“前驱” 最后把s delete了
p->count = s->count;
if (q != p) {
q->rchild = s->lchild; //重接*q的右子树
}
else
q->lchild = s->lchild; //重接*q的左子树
delete s;
}//if
else {
q = p;
if (!p->rchild) { //被删结点*p无右子树,只需重接其左子树
p = p->lchild;
}//else if
else if (!p->lchild) { //被删结点*p无左子树,只需重接其右子树
p = p->rchild;
}//else if
/*――――――――――将p所指的子树挂接到其双亲结点*f相应的位置――――――――*/
if (!f) root = p; //被删结点为根结点 f为NULL时 删除的是根结点
else if (q == f->lchild) f->lchild = p; //挂接到*f的左子树位置
else f->rchild = p; //挂接到*f的右子树位置
delete q;
}
}
//删除频率低于5的单词 //后序遍历访问删除最方便
void BiSortTree::DeleteBST(BiNode* root) {
if (root == NULL)return;
else {
DeleteBST(root->lchild);
DeleteBST(root->rchild);
if (root->count < 4) {//由于初始建立二叉树时count默认都是0 So 0代表1次 所以小于5次等于小于四次
NextRep(root);
}
}
}
//右中左遍历二叉树 便于高频写入文件
void BiSortTree::WriteBST(BiNode* root) {
//cout << "写入开始" << endl;
if (root == NULL) return;
else {
WriteBST(root->rchild);
{BiNode* r = root;
GetInBST(r); //传递出该点
}
WriteBST(root->lchild);
}
}
//上函数遍历写入文件
void BiSortTree::GetInBST(BiNode* root) {
fstream out;
out.open("Ontfile.txt", ios::out | ios::app);//从末尾写入
if (!out.is_open()) {//判断文件是否能打开
cout << "读取文件失败" << endl;
}
if (root->count > 4)
out << root->WordName << ' ';
}
//二叉排序树
void BiSortTree::TableBST() {
//读取文件
ReadBST();
//删除频率低于5的单词
DeleteBST(GetRoot());
//写入文件
WriteBST(GetRoot());
//计算ASL
FindASL();
}
//计算ASL 层次遍历
void BiSortTree::FindASL() {
BiNode* queue[MAX];//
BiNode* queue1[MAX];
int n = 1; //结点个数
int w[MAX] = { 0 };//记录每层结点个数
int i = 1, front = 0, rear = 0; //front rear 队列头和尾
int front1 = 0, rear1 = 0;//queue1
if (GetRoot() == NULL) {
cout << "根结点为空!" << endl;
return;//节点为空
}
w[i++]++; //每层元素个数 //这里w[0]根结点
queue1[rear1++] = GetRoot();//根结点入队列
while (front1 != rear1) {
while (front1 != rear1) {//将queue1的给queue2
queue[rear++] = queue1[front1++];
}
while (rear != front)//一层的
{
//p = NULL;
BiNode* p = queue[front++]; //第一个元素出队
if (p->lchild) {
queue1[rear1++] = p->lchild;//左孩子入队
w[i]++;
n++; //节点个数
}
if (p->rchild) {
w[i]++;
queue1[rear1++] = p->rchild;//右孩子入队
n++; //个数
}
}
i++;//换层
}
int s1 = 0;
for (int j = 0; j < i; j++)
s1 += (j + 1) * w[j];
cout << "平均检索长度(ASL) = " << s1 * 1.0 / n << endl;
}