实验三源代码

#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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值