实验一 图书管理系统
一.算法实现方案:
1.整体采用顺序表来实现,将每一个图书结构体存储到顺序表中,通过对顺序表的增删改查来实现相应的图书管理系统的相关功能。
2.功能及实现:
1)根据指定图书个数,逐个输入图书信息:
实现:设置input函数,依次创建图书结构体,将创建的图书存储到顺序表里;
2)逐个显示图书表中所有图书的相关信息:
实现:通过循环将顺序表里的图书信息依次输出;
3)能根据指定的待入库的新图书的位置和信息,将新图书插入到图书表中指定的位置:
实现:即顺序表的插入,根据位置插入,该位置后的图书依次后移;
4)根据指定的待出库的旧图书的位置,将该图书从图书表中删除:
实现:即顺序表的删除,根据位置删除图书,其后图书一次后移;
5)能统计表中图书个数:
实现:遍历一遍,count++;
6)实现图书信息表的图书去重:
实现:设置两个循环指针,依次遍历,有重复的实现删除操作;
7)实现最爱书籍查询,根据书名进行折半查找,要求使用非递归算法实现,成功返回书籍的书号和价格:
实现:将顺序表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
8)利用快速排序按照图书价格降序排序:
实现:设置两个指针和一个关键字,从左往右找比关键字小的位置,从右往左找比关键字大的位置,交换位置,重复上述步骤,直至关键字的左侧数字都比其小,右侧数字都比其大。
9)实现最贵图书的查找:
实现:即顺序表的查找,根据价格进行查找,返回图书的价格、书名等内容。
二.代码:
#include
#include
#include
#define MAX 100
using namespace std;
struct Book{
char no[15];
char name[30];
float price;
};
struct Seqlist{
Book elem[MAX];
int length;
};
Seqlist list;
void input(){ //输入
int nums; //书的数目
Book s; //建立每本书的对象
cout<<"请输入您要输入的图书的数目:"<<'\t';
cin>>nums;
int i=list.length;
for(list.length;list.length cout<<"请输入图书的书号、书名、价格:"<<'\t';
cin>>s.no>>s.name>>s.price;
list.elem[list.length]=s;
}
}
void output(Seqlist m){ //输出
cout<<"-----------------------------------------------------------------"< cout<<"|序号| 书 号 | 名 称 | 价 格 |"< for(int i=0;i cout<<"----------------------------------------------------------------"< cout<<"|"< }
cout<<"----------------------------------------------------------------"< }
void insert(){ //插入
int loc;//新图书的位置
Book s;
cout<<"请输入新图书插入的位置:"<<'\t';
cin>>loc;
cout<<"请输入新图书的相关信息:"<<'\t';
cin>>s.no>>s.name>>s.price;
if(loc>0&&loc<=list.length){
for(int i=list.length;i>=loc;i--) list.elem[i]=list.elem[i-1];
list.elem[loc-1]=s;
list.length++;
output(list);
}
else cout<<"抱歉,入库位置非法"< }
void Delete(){ //删除
char booknums[15];int flag=0;
cout<<"请输入要出库的旧图书的书号:"<<'\t';
cin>>booknums;
for(int i=0;i if(strcmp(list.elem[i].no,booknums)==0){
for(int j=i;j list.elem[j]=list.elem[j+1];
list.length--;
flag=1;
}
}
if(flag) output(list);
else cout<<"出库失败,未找到该图书!"< }
void statistic(){
cout<<"图书数目为:"< }
void duplicate(){ //去重
for(int i=0;i for(int j=i+1;j if(strcmp(list.elem[i].no,list.elem[j].no)==0){
for(int k=j;k list.length--;j--;
}
statistic();
output(list);
}
void lovebook(){ //最爱图书的查询
Seqlist love;
char booknames[30];//图书的书名
cout<<"请输入您喜欢的图书的书名:"<<'\t';
cin>>booknames;
love.length=0;
for(int i=0;i if(strcmp(list.elem[i].name,booknames)==0)
love.elem[love.length++]=list.elem[i];
if(love.length==0) cout<<"抱歉,没有你的最爱!"< else{
cout<<"您最爱的图书数目为"< output(love);
}
}
void modify(){ //批量修改
float average;
for(int i=0;i average+=list.elem[i].price;
}
average=average/list.length;
for(int i=0;i if(list.elem[i].price else list.elem[i].price=list.elem[i].price*1.1;
}
output(list);
}
void expensive(){ //最贵图书的查询
Seqlist expen;
float max=list.elem[0].price;
int a=0;expen.length=0;
for(int i=1;i if(max max=list.elem[i].price;
a=i;
}
for(int i=1;i if(list.elem[i].price==max)
expen.elem[expen.length++]=list.elem[i];
cout<<"最贵图书的数目为"< output(expen);
}
void downsort(Book s[],int l,int r){ //图书价格降序排序
if(l int i=l,j=r;
Book key=list.elem[l];
while(i while(i=key.price) j--;
if(i while(i if(i }
list.elem[i]=key;
downsort(s,l,i-1);
downsort(s,i+1,r);
}
}
void selectfun(){
int nums;//选择的功能
cout<<"-----------------------------------------------"< cout<<"|根据指定图书个数,逐个输入图书信息----------1|"< cout<<"|逐个显示图书表中所有图书的相关信息----------2|"< cout<<"|新图书插入到图书表中指定的位置--------------3|"< cout<<"|根据旧图书的位置,将图书从图书表中删除------4|"< cout<<"|统计表中图书个数----------------------------5|"< cout<<"|图书信息表的图书去重------------------------6|"< cout<<"|查询最爱书籍的书号和价格--------------------7|"< cout<<"|图书信息表按指定条件进行批量修改------------8|"< cout<<"|按照图书价格降序排序------------------------9|"< cout<<"|实现最贵图书的查找-------------------------10|"< cout<<"-----------------------------------------------"< cin>>nums;
switch(nums){
case 1:input(); break;
case 2:output(list); break;
case 3:insert(); break;
case 4:Delete(); break;
case 5:statistic(); break;
case 6:duplicate(); break;
case 7:lovebook(); break;
case 8:modify(); break;
case 9:downsort(list.elem,0,list.length-1);output(list);break;
case 10:expensive(); break;
}
}
int main(){
selectfun();
while(1){
char choice;
cout<<"是否选择继续操作(Y or N)"< cin>>choice;
if(choice=='Y'||choice=='y') selectfun();
else if(choice=='N'||choice=='n') break;
else cout<<"输入有误,请重新输入";
}
return 0;
}
实验二 隐式图的搜索
一.算法实现方案:
1 读取初始状态和目标状态,通过逆序数奇偶性判断能否到达。
2 将初始节点压入open表中
3 取出open表中估计值最小的节点,放入close表
4 判断该节点是否为目标节点,不是的话,拓展该节点,将子节点放入open表,返回上一步
5 将该节点压入栈中,并将指针指向父节点
6 如果父节点不为空,继续5
二.代码:
#include
#include
#include"time.h"
#include
#include
using namespace std;
#define num 9
struct Node{
int state[9];
struct Node* parent;
int value;
int depth;
friend bool operator <(Node A,Node B){
return A.value> B.value;
}
};
priority_queue openTable;
queue closeTable; //close表
stack Path; //最终路径
int count1 = 0;
int count2 = 0;
int read(Node& S, Node& G) {
/*初始化*/
S.parent = NULL;
S.depth = 0;
S.value = 0;
G.parent = NULL;
G.depth = 0;
G.value = 0;
cout<<"请输入初始状态\n";
for(int i=0;i
cin>>S.state[i];
cout<<"请输入目标状态?\n";
for(int i=0;i
cin>>G.state[i];
for(int i=0;i
for(int j=i+1;j
if(S.state[i]>S.state[j]&&S.state[i]*S.state[j]!=0)
count1++;
for(int i=0;i
for(int j=i+1;j
if(G.state[i]>G.state[j]&&G.state[i]*G.state[j]!=0)
count2++;
if(count1%2!=count2%2) return 0;
return 1;
}
int value1(Node A,Node G) {
int count = 8;
for (int i=0;i
if(A.state[i]==G.state[i]&&G.state[i]!=0)
count--;
return count + A.depth;
}
int value2(Node A,Node G){
int count=0;
int begin[3][3];
int end[3][3]; //count记录所有棋子移动到正确位置需要的步数
for(int i=0;i
begin[i/3][i%3]=A.state[i];
end[i/3][i%3]=G.state[i];
}
for(int i=0;i<3;i++) //检查当前图形的正确度
for(int j=0;j<3;j++){
if(begin[i][j]==0) continue;
else if(begin[i][j]!=end[i][j]){
for(int k=0;k<3;k++)
for(int w=0;w<3;w++)
if(begin[i][j]==end[k][w])
count=count+fabs(i-k*1.0)+fabs(j-w*1.0);
}
}
return count + A.depth;
}
bool judge(Node S,Node G){
for(int i=0;i<9;i++){
if(S.state[i]!=G.state[i]) return false;
}
return true;
}
//产生新节点,加入OPEN表
void creatNode(Node& S,Node G){
/* 计算原状态下,空格所在的行列数,从而判断空格可以往哪个方向移动 */
int blank; //定义空格下标
for(blank=0;blank<9&&S.state[blank]!=0;blank++);//找到空白格
int x=blank/3,y=blank%3; //获取空格所在行列编号
for(int d=0;d<4;d++){ //找到S扩展的子节点,加入open表中
int newX = x, newY = y;//新空白格坐标
Node tempNode;
/*移动空白格*/
if (d==0) newX=x-1;
if (d==1) newY=y-1;
if (d==2) newX=x+1;
if (d==3) newY=y+1;
int newBlank=newX*3+newY; //空格新的位置
if (newX>=0&&newX<3&&newY>=0&&newY<3){ //如果移动合法
// 交换新旧空白格的内容
tempNode=S;
tempNode.state[blank]=S.state[newBlank];
tempNode.state[newBlank]=0;
if (S.parent!=NULL&&(*S.parent).state[newBlank]==0){ //如果新节点和爷爷节点一样,舍弃该节点
continue;
}
// 把子节点都加入open表中
tempNode.parent=&S;
tempNode.value=value2(tempNode,G);
tempNode.depth=S.depth+1;
openTable.push(tempNode);
}
}
}
int main(){
Node S0,Sg;
if (!read(S0,Sg)){
cout<<"两点之间不可达!";
system("pause");
return 0;
}
clock_t start,finish;
start=clock();
openTable.push(S0);
while (true){
closeTable.push(openTable.top()); //将open表中优先级最高的元素压入close表中
openTable.pop(); //剔除open表中优先级最高的元素
if (!judge(closeTable.back(),Sg)){ //如果当前棋局与目标棋局不相同,则拓展当前节点
creatNode(closeTable.back(),Sg);
}
else break;
}
Node tempNode; //临时变量暂存队前数据
tempNode=closeTable.back();
while (tempNode.parent!=NULL){
Path.push(tempNode);//压入
tempNode=*(tempNode.parent);//指向父节点
}
Path.push(tempNode);
cout<<"至少要移动"<
//输出方案
while(Path.size()!=0){
for(int i=0;i<=8;i++){
cout<
if((i+1)%3==0) cout<
}
Path.pop();
cout<<"\n";
}
finish=clock();
cout<<(finish-start)<<"毫秒";
system("pause");
return 0;
}
实验三 基于线性表和二叉排序树的低频词过滤系统
一.算法实现方案:
1.读取英文文章文件:
分词时可以利用空格或者标点符号作为划分单词依据,文章中默认只包含英文单词和标点符号
2.线性表:建立一个单词结构体,包含单词名称、单词频率;当识别出一个单词后,若线性表中没有该单词,则在适当的位置上添加该单词;若该单词已经被识别,则增加其出现的频率。
3.二叉排序树:方法基本同2,通过二叉排序树来实现。
二.代码:
#include
#include
#include
#include
#define NUM 5
using namespace std;
void Sort(vector> &WordList,vector &WordNum,int n) { //将单词表中的单词按照出现频率从大到小排序
for(int i=0;i for(int j=i;j if(WordNum[i] int temp=WordNum[i];
WordNum[i]=WordNum[j];
WordNum[j]=temp;
vector Temp=WordList[i];
WordList[i]=WordList[j];
WordList[j]=Temp;
}
}
int repeat(vector> WordList,vector word){ //判断单词表WordList中是否存在单词word,若存在则返回位置,否则返回0.
for (int i=0;i if(WordList[i]==word) return i+1;
return 0;
}
double Readword(ifstream &infile,vector> &WordList,vector &WordNum) { //存储文件中的单词及数量
double ASL=0; //平均查找次数
vector word; //单词存储器
char ch; //字母存储器
int loction; //记录单词在单词表中的位置
if(infile){
while((ch=infile.get())!=EOF){
if(ch>=65&&ch<=90) ch+=32; //大写字母转换成小写
if (ch>=97&&ch<=122) word.push_back(ch); //小写字母放在单词后面
else if(!repeat(WordList,word)){ //如果没找到
WordNum.push_back(1); //新单词的频率为1
WordList.push_back(word); //在单词表中加入新单词
word.clear(); //清空单词存储器
ASL+=WordList.size(); //查找次数增加单词表的长度
}
else{
loction=repeat(WordList,word); //判断单词表中是否存在新单词word
WordNum[loction-1]++; //新单词的频率加1
word.clear(); //清空单词存储器
ASL+=loction; //查找次数增加找到新单词的位置
}
}
}
else cout<<"打开文件错误!"< cout<<"识别完毕!"< return ASL/WordList.size(); //返回平均查找次数
}
void Prlittle(vector> &WordList,vector &WordNum){ //显示单词表中少于频率阈值的单词输出并从单词表中删除
cout<<"单词数少于"< for(int i=0;i if(WordNum[i] for(auto j:WordList[i]) cout< cout<<"("< WordList.erase(begin(WordList)+i);
WordNum.erase(begin(WordNum)+i);
i--;
}
cout< }
void Prresidue(vector> &WordList,vector &WordNum){ //显示并在新文件中输入排好序的剩余单词
ofstream ofs; //输出流对象
ofs.open("Outfile.txt",ios::ate); //打开输出文件
if(!ofs){
cout<<"打开文件产生错误"< return;
}
cout<<"剩余单词及其数量为:"< Sort(WordList,WordNum,WordList.size()); //对单词表中的单词进行排序
for(int i=1;i for(auto j:WordList[i]){ //依次输出单词
cout< ofs< }
cout<<"("< ofs<<"("< }
cout< ofs.close(); //关闭输出文件
}
int allPath(ifstream &infile,vector> &WordList,vector &WordNum){ //执行所有步骤,返回执行时间(ms)
int begintime,endtime; //开始时间,结束时间
begintime=clock(); //记录开始的时间
double x=Readword(infile,WordList,WordNum);
Prlittle(WordList,WordNum);
Prresidue(WordList,WordNum);
cout<<"ASL值为:"< endtime=clock(); //记录结束的时间
return endtime - begintime; //返回两者差
}
void Linear() { //线性表的人机交互界面
ifstream infile; //输入流对象
infile.open("Infile.txt"); //打开要读取的文件
vector> WordList; //单词表
vector WordNum; //单词频率表
int n,time=0; //记录用户的输入,记录时间
double ASL; //ASL值
bool t=true; //控制程序退出
bool s1=false,s3=false,s4=false; //控制程序的执行顺序
while(t){
system("cls"); //防止页面过于繁杂,执行一次清屏
cout<<"1.连续执行至完毕\n"<<"2.显示执行时间\n"<<"3.单步执行,识别并统计单词\n"<<"4.单步执行,删除并显示出现频率低单词\n"<<"5.单步执行,输出其余单词及其频率\n"<<"6.单步执行,计算并输出ASL值\n"<<"7.返回主菜单"< cin>>n;
switch(n){
case 1:if(s1||s3){
cout<<"单词已经识别,请勿重复识别!" < break;
}
else{
time=allPath(infile, WordList, WordNum);
s1 = true;
break;
}
case 2:if(s1){
cout<<"运行时间为:"< break;
}
else{
cout<<"程序还未执行!"< break;
}
case 3:if(s1||s3){
cout<<"单词已经识别,请勿重复识别!" < break;
}
else{
ASL=Readword(infile, WordList, WordNum);
s3=true;
break;
}
case 4:if(s4){
cout<<"单词已删除!"< break;
}
else if(s3){
Prlittle(WordList, WordNum);
s4=true;
break;
}
else{cout<<"未识别单词!"< break;
}
case 5:if(s4){
Prresidue(WordList, WordNum);
break;
}
else{
cout<<"未删除单词!"< break;
}
case 6:if(s3){
cout<<"ASL值为:"< break;
}
else{
cout<<"未识别单词!"< break;
}
case 7:t=false; break;
default:cout << "选择错误,请重新输入:";
}
system("pause"); //暂停,给用户观察的时间
}
infile.close(); //关闭输入流对象
}
typedef struct BSTNode {
string WordName; //单词名称
int count; //单词出现频率
int height; //单词当前高度
struct BSTNode *lchild, *rchild; //左右子树
}BSTNode,*BSTree;
void InsertnewTree(BSTree &newRoot,BSTree &root) { //递归生成频数二叉排序树
if(newRoot==NULL){
newRoot=new BSTNode;
newRoot->WordName=root->WordName;
newRoot->count=root->count;
newRoot->height=0;
newRoot->lchild=NULL;
newRoot->rchild=NULL;
}
else{
if(newRoot->count<=root->count )
return InsertnewTree(newRoot->rchild,root);
else return InsertnewTree(newRoot->lchild,root);
}
}
void PrintLittleWord2(BSTree &newRoot,BSTree &root) { //后序遍历
if(root==NULL)return;
else{
PrintLittleWord2(newRoot,root->lchild);
PrintLittleWord2(newRoot,root->rchild);
if(root->count printf("%s%c%d%s",root->WordName.c_str(),'(',root->count,")\n");
else InsertnewTree(newRoot,root); //否则插入新树
}
}
int InsertTree(BSTree &root,string word,bool &isInsert,int h = 1){ //递归插入二叉排序树,返回插入所在的高度
if(root==NULL){
root=new BSTNode;
root->WordName=word;
root->count=1;
root->height=h;
root->lchild=NULL;
root->rchild=NULL;
isInsert=false;
return h;
}
else{
if(root->WordName.compare(word)==0){
root->count++;
isInsert=true;
return h;
}
else if(root->WordName.compare(word)==-1)
return InsertTree(root->lchild,word,isInsert,h+1);
else return InsertTree(root->rchild,word,isInsert,h+1);
}
}
double Readword2(ifstream &infile,BSTree &root){
double ASL=0; //平均查找长度
char Word[20]; //存放单词的字符数组
int num=0; //不同的单词数量
bool isInsert=true; //判断单词表中是否存在该单词(初值不影响使用)
if(infile){
char ch; //存放字母
int n=0; //控制位置,记录单词长度
while((ch=infile.get())!=EOF){
if(ch>=65&&ch<=90) ch+=32; //大写变小写
if(ch>=97&&ch<=122){
Word[n]=ch;
n++;
}
else{
string word(&Word[0],&Word[n]); //字符数组转化成字符串
ASL+=InsertTree(root,word,isInsert); //ASL增加插入成功所在的高度数
word.clear(); //清空单词存储器
n=0; //重置n
if(!isInsert) num++; //如果不存在,单词总数加1
}
}
}
else cout<<"打开文件错误!"< cout<<"识别完毕!"< return ASL/num; //返回平均查找次数
}
void InOrder(ofstream &ofs,BSTree &newRoot){ //反中序输出二叉排序树(从大到小输出)
if(newRoot==NULL) return;
else{
InOrder(ofs,newRoot->rchild);
if(newRoot->count!=0){
cout InOrder(ofs,newRoot->lchild);
}
}
void Prresidue2(BSTree &newRoot){ //反中序输出二叉排序树(从大到小输出)
ofstream ofs; //输出流对象
ofs.open("Outfile.txt",ios::ate); //打开输出文件
if(!ofs){
cout<<"打开文件错误!"< return;
}
cout<<"剩余单词及其数量为:"< BSTree p=newRoot;
while(p->rchild){
p=p->rchild;
}
p->count=0; //标记频率最大的符号位
InOrder(ofs,newRoot);
ofs.close(); //关闭输出流对象
}
void POD(BSTree &root) { //后序遍历析构二叉排序树
if(root==NULL) return;
else{
POD(root->rchild);
POD(root->lchild);
delete root;
}
}
int allPath2(ifstream &infile,BSTree newRoot,BSTree root){ //执行所有步骤,返回执行时间(ms)
int begintime,endtime;
begintime=clock();
double x=Readword2(infile,root);
cout<<"单词数少于"< PrintLittleWord2(newRoot,root);
Prresidue2(newRoot);
cout<<"ASL值为:"< endtime=clock();
return endtime-begintime;
}
void BST(){ //排序二叉树的人机交互界面
BSTree root=NULL; //排序二叉树
BSTree newRoot=NULL; //新排序二叉树
int n,time=0; //记录用户的输入,记录时间
double ASL;
bool t=true; //控制程序退出
ifstream infile; //输入流对象
infile.open("Infile.txt"); //打开要读取的文件
bool s1=false,s3=false,s4=false; //控制程序的执行顺序
while(t){
cout<<"1.连续执行至完毕\n"<<"2.显示执行时间\n"<<"3.单步执行,识别并统计单词\n"<<"4.单步执行,删除并显示出现频率低单词\n"<<"5.单步执行,输出其余单词及其频率\n"<<"6.单步执行,计算并输出ASL值\n"<<"7.返回主菜单"< cin>>n;
switch(n){
case 1:if(s1||s3){
cout<<"单词已经识别,请勿重复识别!" << endl;
break;
}
else{time=allPath2(infile,newRoot,root);
s1=true;
break;
}
case 2:if(s1){
cout<<"运行时间为:"< break;
}
else{cout<<"程序还未执行!"< break;
}
case 3:if(s1||s3){
cout<<"单词已经识别,请勿重复识别!"< break;
}
else{ASL=Readword2(infile,root);
s3=true;
break;
}
case 4:if(s4){
cout<<"单词已删除!"< break;
}
else if(s3){
cout<<"单词数少于"< PrintLittleWord2(newRoot,root);
s4=true;
break;
}
else{
cout << "未识别单词!" << endl;
break;
}
case 5:if(s4){
Prresidue2(newRoot);
break;
}
else{
cout<<"未删除单词!"< break;
}
case 6:if(s3){
cout<<"ASL值为:"< break;
}
else{
cout<<"未识别单词!"< break;
}
case 7:t=false; break;
default:cout<<"选择错误,请重新输入:";
}
system("pause");
}
POD(root); //释放排序二叉树的内存
POD(newRoot); //释放新排序二叉树的内存
infile.close(); //关闭输入流对象
}
int main(){
int m,t=1; //控制程序退出
while(t){
cout<<"1.线性表\n"<<"2.二叉排序树\n"<<"3.退出系统\n"<<"请选择你需要的服务,输入数字(1~3):"< cin>>m;
switch(m){
case 1:Linear(); break;
case 2:BST(); break;
case 3:t=0; break;
default:cout<<"选择错误,请重新输入:";
}
}
return 0;
}