数据结构实验1源码

合集下载

【数据结构算法】实验1 线性表应用-多项式计算(附源代码)

【数据结构算法】实验1 线性表应用-多项式计算(附源代码)

浙江大学城市学院实验报告课程名称数据结构与算法实验项目名称实验一线性表应用---多项式计算实验成绩指导老师(签名)日期一.实验目的和要求1.进一步掌握线性表的的基本操作。

2.掌握线性表的典型应用----多项式表示与计算。

二. 实验内容1.设用线性表( (a1, e1), (a2, e2), ……, (am, em) ) 表示多项式P(x) = a1*x e1 + a2*x e2+…+ am*x em,其中:a1~am为非零系数,0≤e1<e2<…..<em,请编写用链式存储结构(带表头附加结点的单链表)存储该多项式时,多项式基本操作的实现函数。

多项式基本操作应包括初始化多项式、清除多项式、输出多项式、插入一项、删除一项、多项式求值、多项式相加等。

要求:把多项式线性表的结构定义及多项式基本操作实现函数存放在头文件Linkpoly.h中,主函数存放在主文件test6_1.cpp中,在主函数中通过调用Linkpoly.h中的函数进行测试。

2.选做:编写用顺序存储结构存储多项式时,多项式基本操作的实现函数。

要求:把多项式线性表的结构定义及多项式基本操作实现函数存放在文件Seqpoly.h中,在主文件test6_1.cpp中增加测试语句对Seqpoly.h中的函数进行测试。

3.填写实验报告,实验报告文件取名为report1.doc。

4.上传实验报告文件report1.doc与源程序文件test6_1.cpp及Linkpoly.h、Seqpoly.h(若有)到Ftp服务器上自己的文件夹下。

三. 函数的功能说明及算法思路包括每个函数的功能说明,及一些重要函数的算法实现思路※注1:除了[多项式求值]与[多项式相加]两个函数外,线性表的基本操作函数,大部分沿用上学期[线性表的链式/顺序表示和实现]两个实验中的函数。

※注2:选作部分函数功能与思路与非选作部分基本一致,略去思路描述函数:void InitList(LNode *&H)功能:初始化单链表思路:使用附带头结点的方式初始化单链表函数:int LengthList (LNode *H)功能:求单链表长度思路:遍历整个单链表,设置变量记录并返回它的长度函数:bool EmptyList (LNode *H)功能:判断单链表是否为空表思路:判断头结点的后一结点是否为空,若空则为空表函数:void TraverseList(LNode *H)功能:遍历单链表思路:遍历整个单链表,输出所含所有元素函数:bool InsertList ( LNode *&H, ElemType item, int pos)功能:向单链表插入一个元素思路:创建新结点,根据pos的值来确定位置并向单链表中插入新元素。

数据结构上机实验源代码

数据结构上机实验源代码

数据结构上机实验源代码栈的应用十进制数转换为八进制数,逆序输出所输入的数实验代码://stack.h,头文件class stack{public:stack();bool empty()const;bool full()const;error_code gettop(elementtype &x)const;error_code push(const elementtype x);error_code pop();private:int count;elementtype data[maxlen];};stack::stack(){count=0;}bool stack::empty()const{return count==0;}bool stack::full()const{return count==maxlen;}error_code stack::gettop(elementtype &x)const{if(empty())return underflow;else{x=data[count-1];return success;}}error_code stack::push(const elementtype x){if(full())return overflow;data[count]=x;count++;return success;}error_code stack::pop(){if(empty())return underflow;count--;return success;}//主程序#include<iostream.h>enum error_code{overflow,underflow,success};typedef int elementtype;const int maxlen=20;#include"stack.h"void read_write() //逆序输出所输入的数{stack s;int i;int n,x;cout<<"please input num int n:";cin>>n;for(i=1;i<=n;i++){cout<<"please input a num:";cin>>x;s.push(x);}while(!s.empty()){s.gettop(x);cout<<x<<" ";s.pop();}cout<<endl;}void Dec_to_Ocx(int n) //十进制转换为八进制{stack s1;int mod,x;while(n!=0){mod=n%8;s1.push(mod);n=n/8;}cout<<"the ocx of the dec is:";while(!s1.empty()){s1.gettop(x);cout<<x;s1.pop();}cout<<endl;}void main(){int n;// read_write();cout<<"please input a dec:";cin>>n;Dec_to_Ocx(n);}队列的应用打印n行杨辉三角实验代码://queue.hclass queue{public:queue(){count=0;front=rear=0;}bool empty(){return count==0;}bool full(){return count==maxlen-1;}error_code get_front(elementtype &x){if(empty())return underflow;x=data[(front+1)%maxlen];return success;}error_code append(const elementtype x){if(full())return overflow;rear=(rear+1)%maxlen;data[rear]=x;count++;return success;}error_code serve(){if(empty())return underflow;front=(front+1)%maxlen;count--;return success;}private:int count;int front;int rear;int data[maxlen];};//主程序#include<iostream.h>enum error_code{overflow,underflow,success};typedef int elementtype;const int maxlen=20;#include"queue.h"void out_number(int n) //打印前n行的杨辉三角{int s1,s2;int i;int j;int k;queue q;for(i=1;i<=(n-1)*2;i++)cout<<" ";cout<<"1 "<<endl;q.append(1);for(i=2;i<=n;i++){s1=0;for(k=1;k<=(n-i)*2;k++)cout<<" ";for(j=1;j<=i-1;j++){q.get_front(s2);q.serve();cout<<s1+s2<<" ";q.append(s1+s2);s1=s2;}cout<<"1 "<<endl;q.append(1);}}void main(){int n;cout<<"please input n:";cin>>n;out_number(n);}单链表实验实验目的:实验目的(1)理解线性表的链式存储结构。

数据结构试验完整代码

数据结构试验完整代码

数据结构实验完整代码目录一、顺序存储的线性表 (2)二、单链存储的线性表 (4)三、栈 (7)四、队列 (8)五、二叉树的建立和遍历 (10)六、霍夫曼树 (11)七、图的建立和遍历 (17)图的邻接矩阵表示 (17)图的邻接表表示 (20)八、图的最小生成树 (23)九、图的最短路径 (28)十、顺序查找表 (31)十一、二叉排序树的查找 (34)十二、哈希表 (36)十三、插入排序 (41)十四、交换排序-冒泡排序 (44)十五、交换排序-快速排序 (45)十六、简单选择排序 (45)十七、堆排序 (46)一、顺序存储的线性表typedef struct{char name[10];char no[10];double grade;}Student;typedef struct{Student *elem;int length;int listsize;}SqList;void Display(SqList *L){int i;for (i=0;i<L->length ;i++){cout<<i+1<<":姓名"<<L->elem[i].name<<",学号:"<<L->elem[i].no<<",成绩:"<<L->elem[i].grade <<endl;}cout<<"请选择菜单项:";}SqList *CreateList(){SqList *L;L=(SqList*)malloc(sizeof(SqList));if(!L) cout<<"建立线性表失败!";else cout<<"建立线性表成功!";return(L);}int InitList(SqList *L){int i;char name[10],no[10];double grade;L->elem=(Student *)malloc(ListInitSize * sizeof(Student));if (!(L->elem)) cout<<"初始化表失败!";L->length = 0;L->listsize = ListInitSize;cout<<"请输入要录入信息的学生个数:"<<endl;cin>>i;if (i>(L->listsize)){L->elem =(Student *)realloc(L->elem ,i*sizeof(Student));}for (int j=0;j<i;j++){cout<<"请输入第"<<j+1<<"个学生的信息:"<<endl;cin>>name>>no>>grade;strcpy((L->elem+L->length)->name,name);strcpy((L->elem+L->length)->no,no);(L->elem+L->length)->grade =grade;L->length ++;}cout<<"信息录入完成!";return 0;}int Insert(SqList *l){Student e;int i,j;Student *newbase;cout<<"请输入要插入的位置:";cin>>j;j--;cout<<"请输入学生信息:";cin>>>>e.no>>e.grade;if(l->length==l->listsize){newbase=(Student*)realloc(l->elem,(l->listsize+ListIncreasement)*sizeof(Studen t));if(!newbase){cout<<"出错!";return 0;}l->elem=newbase;l->listsize+=ListIncreasement;}for(i=l->length;i>=j;i--){l->elem[i+1] = l->elem[i];}l->elem[j]=e;l->length++;cout<<"插入成功!";return 0;}int Delect(SqList *L){int i,j;cout<<"输入删除信息的位置:";cin>>j;j--;cout<<"删除的信息为:姓名:"<<L->elem[j].name<<",学号:"<<L->elem[j].no<<"成绩:"<<L->elem[j].grade<<endl;for(i=j+1;i<=L->length;i++){L->elem[i-1]=L->elem[i];}L->length--;cout<<"请按回车继续"<<endl;getchar();getchar();cout<<"删除成功!";return 0;}二、单链存储的线性表typedef struct Student{char name[10];char no[10];double grade;}Student;typedef struct LNode{Student data;LNode *next;}LNode,*LinkList;void CreateList(LinkList &l){l=(LinkList)malloc(sizeof(LNode));if (!l) cout<<"建立失败。

数据结构与算法实验源代码

数据结构与算法实验源代码

数据结构与算法实验源代码数据结构与算法实验源代码1.实验目的本实验旨在通过实践,加深对数据结构与算法的理解与应用能力,掌握数据结构和算法的基本概念与原理,并能够运用所学知识解决实际问题。

2.实验材料●一台已安装好编译器的计算机●数据结构与算法实验源代码文件3.实验环境配置在实验开始之前,必须确保计算机上已安装好以下环境:●编译器(可以是C++、Java等)●数据结构与算法实验源代码文件4.实验内容及步骤4.1 实验一:线性表4.1.1 实验目的通过实现线性表的相关操作,加深对线性表及其操作的理解,并能够灵活应用。

4.1.2 实验步骤1.实现线性表的初始化函数2.实现线性表的插入操作3.实现线性表的删除操作4.实现线性表的查找操作5.实现线性表的排序操作6.实现线性表的输出操作7.编写测试代码,对线性表进行测试4.1.3 实验结果与分析进行若干测试用例,验证线性表的正确性,并分析算法的时间复杂度与空间复杂度。

4.2 实验二:栈与队列4.2.1 实验目的通过实现栈与队列的相关操作,加深对栈与队列的理解,并掌握栈与队列的应用场景。

4.2.2 实验步骤1.实现栈的初始化函数2.实现栈的入栈操作3.实现栈的出栈操作4.实现栈的查看栈顶元素操作5.实现队列的初始化函数6.实现队列的入队操作7.实现队列的出队操作8.实现队列的查看队首元素操作4.2.3 实验结果与分析进行若干测试用例,验证栈与队列的正确性,并分析算法的时间复杂度与空间复杂度。

(继续添加实验内容及步骤,具体根据实验项目和教学要求进行详细分析)5.实验附件本文档所涉及的实验源代码文件作为附件随文档提供。

6.法律名词及注释6.1 版权:著作权法所规定的权利,保护作品的完整性和原创性。

6.2 开源:指软件可以被任何人免费使用、分发和修改的一种软件授权模式。

(继续添加法律名词及注释)。

《数据结构》实验指导书(源代码)

《数据结构》实验指导书(源代码)

实验一线性表的链式存储结构一、实验目的:1.掌握线性表的链式存储结构。

2.熟练地利用链式存储结构实现线性表的基本操作。

3.能熟练地掌握链式存储结构中算法的实现。

二、实验内容:1.用头插法或尾插法建立带头结点的单链表。

2.实现单链表上的插入、删除、查找、修改、计数、输出等基本操作。

三、实验要求:1. 根据实验内容编写程序,上机调试、得出正确的运行程序。

2. 写出实验报告(包括源程序和运行结果)。

四、实验学时:2学时五、实验步骤:1.进入编程环境,建立一新文件;2. 参考以下相关内容,编写程序,观察并分析输出结果。

①定义单链表的数据类型,然后将头插法和尾插法、插入、删除、查找、修改、计数、输出等基本操作都定义成子函数的形式,最后在主函数中调用它,并将每一种操作前后的结果输出,以查看每一种操作的效果。

②部分参考程序//单链表的建立(头插法),插入,删除,查找、修改、计数、输出#include<iostream.h>#define elemtype intstruct link{ elemtype data;//元素类型link *next; //指针类型,存放下一个元素地址};//头插法建立带头结点的单链表link *hcreat(){ link s,p;elemtype i;cout<<”输入多个结点数值(用空格分隔),为0时算法结束”;cin>>i;p=new link;p->next=NULL;while(i) //当输入的数据不为0时,循环建单链表{s=new link;s->data=i;s->next=p->next;p->next=s;cin>>i; }return p;}//输出单链表void print(1ink *head){1ink *p;p=head->next;while(p->next!=NULL){cout<<p->data<<”->”; //输出表中非最后一个元素p=p->next;}cout<<p->data; //输出表中最后一个元素cout<<endl;}∥在单链表head中查找值为x的结点Link *Locate(1ink *head,elemtype x){Link *p;p=head->next;while((p!=NULL)&&(p->data!=x))p=p->next;return p; }//在head为头指针的单链表中,删除值为x的结点void deletel(1ink *head,elemtype x){1ink *p, *q;q=head;p=head->next;while((p!=NULL)&&(p->data!=x)){q=p;p=p->next;}If(p==NULL) cout<<“要删除的结点不存在”;elseq->next=p ->next;delete(p);}}//在头指针head所指的单链表中,在值为x的结点之后插入值为y的结点void insert(1ink *head,elemtype x,elemtype y){ link *p, *s;s=new link;s->data=y;if(head->next==NULL) //链表为空{head->next=s;s->next=NULL:}p=Locate(head,x);//调用查找算法‘if(p==NULL)cout<<”插入位置非法”:else(s->next=p->next;p->next=s;}}//将单链表p中所有值为x的元素修改成y void change(1ink *p,elemtype x,elemtype y) {link *q;q=p->next;while(q!=NULL){ if(q->data==x) q->data=y;q=q->next;}}void count(1ink *h) //统计单链表中结点个数{1ink *p;int n=0;p=h->next;while(p!=NULL){n++;p=p->next;}return n;}void main(){ int n;elemtype x,y;link *p, *q;p=hcreat(); //头插法建立链表print(p); //输出刚建立的单链表cout<<”请输入要删除的元素”;cin>>y;deletel(p,y);print(p); //输出删除后的结果cout<<”请输入插入位置的元素值(将待插元素插入到它的后面)”; cin>>x;cout<<”请输入待插元素值”;cin>>y;insert(p,x,y);print(p); //输出插入后的结果cout<<”请输入要修改前、后的元素值”;cin>>x>>y;change(p,x,y);print(p);cout<<”请输入要查找的元素值”;cin>>x;q=Locate(p,x);if(q==NULL)cout<<x<<”不在表中,找不到!”<<endl;else cout<<x<<”在表中,已找到!”<<endl;n=count(p);cout<<”链表中结点个数为:”<<n<<endl:}//单链表的建立(尾插法)、插入、删除、查找、修改、计数、输出#include<iostream.h>#define elemtype intstruct link{ elemtype data;//元素类型link *next;//指针类型,存放下-个元素地址};//尾插法建立带头结点的单链表link *rcreat(){link *s, *p, *r;elemtype i;cout<<”输入多个结点数值(用空格分隔),为0时算法结束”; cin>>i;p=r=new link;p->next=NULL;while(i){s=new link;s->data=i;r->next=s;r=s;cin>>i; }r->next=NULL;return p;}//输出单链表void print(1ink *head){link *p;p=head->next;while(p->next!=NULL){cout<<p->data<<"->”; //输出表中非最后一个元素p=p->next;)cout<<p->data; //输出表中最后一个元素cout<<endl;}link *Locate(1ink *head,int x) ∥在单链表中查找第x个结点 {link *p;p=head;int j=0;while((p!=NULL)&&(j<x)){p=p->next; j++;}return p;}void delete I(1ink *head,elemtype x)//在head为头指针的单链表中,删除值为x的结点{link *p, *q;q=head;p=head->next;while((p!=NULL)&&(p->data!=x)){q=p;p=p->next;)if(p==NULL)cout<<”要删除的结点不存在“;else{q->next=p->next;delete(p);} }void insert(1ink *head,int x,elemtype y)//在头指针head所指单链表中,在第x个结点之后插入值为y的结点{link *p, *s;s=new link;s->data=y;if(head->next==NULL)//链表为空{head->next=s;s->next=NULL:}p=Locate(head,x); //调用查找算法if(p==NULL)cout<<”插入位置非法”;else{s->next=p->next;p->next=s;}}void change(1ink *p,elemtype x,elemtype y){∥将单链表P中所有值为x的元素改成值为ylink *q;q=p->next;while(q!=NULL){if(q->data==x)q->data=y;q=q->next;}}void count(1ink *h) //统计单链表中结点个数(1ink *p;int n=0;p=h->next;while(p!=NULL){n++;p=p->next;}retum n;}void main(){ int n;link p,q;p=rcreat();//尾插法建立链表print(p); //输出刚建立的单链表cout<<”请输入要删除的元素”;cin>>y;deletel(p,y);print(p); //输出删除后的结果cout<<”请输入插入位置”;cin>>x;cout<<”请输入待插元素值”;cin>>y;insert(p,x,y);print(p); //输出插入后的结果cout<<”请输入修改前、后的元素值”;cin>>x>>y;change(p,x,y);print(p);cout<<“请输入要查找的元素值”;cin>>x;q=Locate(p ,x);if(q==NULL)cout<<x<<”不在表中,找不到!”<<endl;else cout<<x<<”在表中,已找到!”<<endl;n=count(p);cout<<”链表中结点个数为:”<<n<endl;}六、选作实验试设计一元多项式相加(链式存储)的加法运算。

实验报告数据结构课程设计源代码

实验报告数据结构课程设计源代码

表达式类型的实现——实习报告一.需求分析1. 编写一个程序,通过前缀表达式来构造一个与之对应的算术表达式并存入二叉树中,通过中序遍历二叉树输出表达式及对其进行变量赋值,通过后序遍历二叉树计算表达式的值。

2. 本程序功能有:存储表达式、对表达式进行赋值计算、求偏导、计算三角函数、合并常数及接受原书写形式的表达式。

3. 测试数据(1). 分别输入0 ; a ; -91 ; +a*bc ; +*5^x2*8x ; +++*3^x3*2^x2x6并输出。

(2). 每输入一个表达式,对其中的变量进行赋值,再对表达式求值。

二.概要设计按照要求,需要以二叉树来存储表达式,但在构造过程中还需要用到栈来实现前缀表达式与二叉树之间的转换。

1. 抽象数据类型栈的定义:ADT SqStack{数据对象:D={ai |ai为整型或字符型}数据关系:R={<ai , ai-1> |ai ,ai-1∈D}基本操作:Status InitStack(SqStack&S);此函数用于创建一个空栈Status StackEmpty(SqStack S);此函数用于判断栈是否为空Status StackFull(SqStack S);此函数用于判断栈是否已满Status Push(SqStack&S, SElemType e);将数据元素e入栈Status Pop(SqStack&S, SElemType&e);出栈,并以e返回出栈的元素Status GetTop(SqStack S, SElemType&e);若栈不空,则以e返回栈顶元素}ADT SqStack2. 二叉树表达式数据类型ATD BiTNode{数据对象:D= { a i | a i∈SqStack}数据关系:R= {<ai , ai-1> |ai ,ai-1∈D}基本操作:Status InputExpr(char*string,int flag);以字符串形式读取输入void JudgeValue(BiTree*E,char*string,int i);判断字符string[i],如果是'0'-'9'常量之间,二叉树结点存为整型;否则,存为字符型 Status ReadExpr(BiTree*E,char*exprstring);以正确的前缀表示式并构造表达式EStatus PriCmp(char c1,char c2);如果两个字符是运算符,比较两个运算符的优先级,c1比c2优先,返回OK,否则返回ERRORvoid WriteExpr(BiTree E);用带括弧的中缀表达式输出表达式void Assign(BiTree*E,char V,int c,int*flag);实现对表达式中的所有变量V的赋值(V=c),参数flag为表示是否赋值过的标志long Operate(int opr1,char opr,int opr2);运算符运算求值,参数opr1,opr2为常量,opr为运算符,根据不同的运算符,实现不同的运算,返回运算结果double Operate1(char opr,double opr1);三角函数运算求值,参数opr为常量,opr1为运算符,根据不同的运算符,实现不同的运算,返回运算结果Status Check(BiTree E);检查表达式是否还存在没有赋值的变量,以便求算数表达式的值long Value(BiTree E);对算术表达式求值void CompoundExpr(char P,BiTree&E1,BiTree E2);构造一个新的复合表达式Status ReadInorderExpr(char*string,char*pre_expr);以表达式的原书写形式输入,表达式的原书写形式字符串string变为字符串pre_expr,后调用reversal_string()函数反转得到前缀表达式pre_exprvoid ReversalString(char*exprstring);将字符串exprstring反转过来void MergeConst(BiTree*E);常数合并操作函数,合并表达式E中所有常数运算int IsOperator(char c);判断是否操作符void Diff(BiTree&E,char v);求偏导数}ADT BiTNode3. 主程序int main() {while(TRUE) {判断用户选择的操作;执行所选操作,并适时提示用户输入及输出运算结果;若用户选择退出,则执行exit(0)退出程序;};4. 程序调用关系:主程序模块三.详细设计1. 数据类型:二叉树数据类型:typedef enum{INT,CHAR}ElemTag;/*INT为整型数据num,CHAR为字符型数据c*/typedef struct TElemType{ElemTag tag;/*{INT,CHAR}指示是整型还是字符型*/int num;/*tag=INT时,为整型*/char c;/*tag=CHAR时,为字符型*/}TElemType;二叉树节点类型:typedef struct BiTNode{TElemType data;/* 二叉树存储的数据*/struct BiTNode*lchild,*rchild; /* 左右孩子指针*/}BiTNode,*BiTree;2. 函数实现:(以伪码表示)Status InputExpr(char *string,int flag) //此函数用于表达式的输入与存储{if(flag==0)cout<<"\n请输入正确的前缀表示式:";else cout<<"\n请以表达式的原书写形式输入正确表示式:";fflush(stdin);/*清理缓冲区*/gets(string);/*从键盘输入一串字符串作为表达式*/if(strlen(string)==1)/*输入的表达式字符串长度为1*/if(string[0]=='+'||string[0]=='-'||string[0]=='*'||string[0]=='/'||string[0]=='^')/*输入的表达式只有一个运算符*/{cout<<"\n表达式只有一个字符,为运算符,错误!";return ERROR;}else if((string[0]>='0'&&string[0]<'9')||(string[0]>='a'&&string[0]<='z')||(string[0]>='A'&&string[0]<='Z')) /*输入的表达式只有一个数字或字符*/{cout<<"\n表达式只有一个字符!";return OK;}else {cout<<"\n输入的字符不是运算符也不是变量常量,错误!";return ERROR;}return OK;}void JudgeValue(BiTree *E,char *string,int i) //此函数用于判断字符string[i],如果是'0'-'9'常量之间,二叉树结点存为整型;否则,存为字符型{if(string[i]>='0'&&string[i]<='9') {(*E)->data.tag=INT;(*E)->data.num=string[i]-'0';}//string[i]为常量else if(string[i]>='10'&&string[i]<='20') {(*E)->data.tag=INT;(*E)->data.num=SaveNumber[string[i]];} //string[i]为常量,存于数组save_number中else {(*E)->data.tag=CHAR;(*E)->data.c=string[i];} /*string[i]为变量,对数据进行变量标记}/*以正确的前缀表示式并构造表达式E*/Status ReadExpr(BiTree *E,char *exprstring){定义栈;为树的根结点分配空间;len=strlen(exprstring);/*len赋值为表达式的长度*/if(len==1) JudgeValue(E,exprstring,0);/*将exprstring[0]存入二叉树的结点中*/else {JudgeValue(E,exprstring,0);/*将exprstring[0]存入二叉树的结点中*/InitStack(S);/*初始化栈*/q=(*E);Push(S,q);/*入栈*/Push(S,q);/*入栈,根结点入栈两次是为判断先序输入的表达式是不是正确的表达式*/for(i=1;i<len&&!StackEmpty(S);i++){p=(BiTree)malloc(sizeof(BiTNode));JudgeValue(&p,exprstring,i);/*将exprstring[i]存入二叉树的结点中*/p->lchild=NULL;p->rchild=NULL;if(exprstring[i]=='+'||exprstring[i]=='-'||exprstring[i]=='*'||exprstring[i]=='/'||exprstring[i]=='^'){/*为运算符,运算符入栈,左孩子不空,向左孩子走,否则,如果右孩子不空,向右孩子走*/if(!q->lchild) {q->lchild=p;Push(S,p);q=p;}else {q->rchild=p;Push(S,p);q=p;}}else /*不是运算符,运算符出栈*/{if(!q->lchild) {q->lchild=p;Pop(S,q);}else {q->rchild=p;Pop(S,q);}}}if(StackEmpty(S)&&i>=len) return OK;/*栈空且i>=len,说明输入的表达式是正确的*/ else /*输入的表达式是错误的*/{cout<<"\n输入的表达式有误!";return ERROR;}}}//此函数用于比较两个运算符的优先级,若c1比c2优先,返回OK,否则返回ERROR Status PriCmp(char c1,char c2){if((c1=='^'||c1=='*'||c1=='-'||c1=='+'||c1=='/')&&(c2=='^'||c2=='*'||c2=='-'||c2=='+'||c2=='/')){/*c1和c2为运算符*/if(c1=='^'){/*c1为指数运算符,则当c2不为'^'时,c1比c2优先*/if(c2!='^') return OK;else return ERROR;}else if(c1=='*'||c1=='/'){/*c1为乘法或除法运算符,则当c2为'+'或'-',c1比c2优先*/if(c2=='^'||c2=='*'||c2=='/') return ERROR;else return OK;}else return ERROR;/*其余,c1不比c2优先*/}else return ERROR;/*c1和c2不是运算符*/}此函数递归实现用带括弧的中缀表达式输出表达式void WriteExpr(BiTree E){if(E)/*树不为空*/{ //先递归左子树if(E->lchild&&E->lchild->data.tag==CHAR)/*E的左孩子不为空,且左孩子为字符*/{if(PriCmp(E->data.c,E->lchild->data.c)){cout<<"(";WriteExpr(E->lchild);cout<<")";}/*带括弧输出左子树*/else WriteExpr(E->lchild);/*否则,不带括弧输出左子树*/}else WriteExpr(E->lchild);/*否则,输出左子树*//*访问输出根结点的值*/if(E->data.tag==INT){cout<<E->data.num;}else cout<<E->data.c;//后递归右子树if(E->rchild&&E->rchild->data.tag==CHAR){//E的右孩子不为空,且右孩子为字符if(PriCmp(E->data.c,E->rchild->data.c)){cout<<"(";WriteExpr(E->rchild);cout<<")";}/*带括弧输出右子树*/else WriteExpr(E->rchild);/*否则,不带括弧输出右子树*/}else WriteExpr(E->rchild);/*否则,输出右子树*/}}此函数递归实现对表达式中的所有变量V的赋值(V=c),参数flag为表示是否赋值过的标志void Assign(BiTree *E,char V,int c,int *flag){if(*E){if((*E)->data.tag==CHAR&&(*E)->data.c==V) {(*E)->data.tag=INT;(*E)->data.num=c;*flag=1;} /*如果找到要赋值的变量,赋值*/Assign(&((*E)->lchild),V,c,flag);/*递归左子树*/Assign(&((*E)->rchild),V,c,flag);/*递归左子树*/}}/*运算符运算求值,参数opr1,opr2为常量,opr为运算符,根据不同的运算符,实现不同的运算,返回运算结果*/long Operate(int opr1,char opr,int opr2){switch(opr){case '+':/*加法*/result=opr1+opr2;return result;break;case '-':/*减法*/result=opr1-opr2;return result;break;case '*':/*乘法*/result=opr1*opr2;return result;break;case '/':/*除法,除法是在整型类型上的除法*/result=opr1/opr2;return result;break;case '^':/*指数运算*/result=pow(opr1,opr2);return result;break;default:break;}}/*三角函数运算求值,参数opr为常量,opr1为运算符,根据不同的运算符,实现不同的运算,返回运算结果*/double Operate1(char opr,double opr1){switch(opr){case 's'://正弦运算result1=sin(opr1);return result1;break;case 'c'://余弦运算result1=cos(opr1);return result1;break;case 't'://正切运算result1=tan(opr1);return result1;break;default:break;}}/*检查表达式是否还存在没有赋值的变量,以便求算数表达式的值*/Status Check(BiTree E){if(E&&E->data.tag==CHAR){/*树不为空*/if(E->data.c!='*'&&E->data.c!='^'&&E->data.c!='-'&&E->data.c!='+'&&E->data.c!='/'){cout<<"\n表达式中仍存在变量没有赋值!没法求出表达式的值!";return ERROR;}/*存在变量,提示信息,后返回ERROR*/if(Check(E->lchild)) Check(E->rchild);}}/*对算术表达式求值*/long Value(BiTree E){if(E){/*树不为空*/if(!E->lchild&&!E->rchild&&E->data.tag==INT) return (E->data.num);/*结点的左孩子和右孩子为空,为叶子结点,返回结点的值*/return Operate(Value(E->lchild),E->data.c,Value(E->rchild));/*运算求值,后根遍历的次序对表达式求值,其中参数递归调用了Value()函数求左子树的值和右子树的值*/}}/*构造一个新的复合表达式*/void CompoundExpr(char P,BiTree &E1,BiTree E2){为结点E申请空间;E->data.tag=CHAR;E->data.c=P;/*申请到的结点值为P*/E->lchild=E1;/*结点的左孩子为E1*/E->rchild=E2;/*结点的右孩子为E2*/E1=E;/*(*E1)为根结点*/cout<<"\n表达式E复合成功!其表达式变为:\n";WriteExpr(E);/*输出复合好的表达式*/}/*此函数以表达式的原书写形式输入,表达式的原书写形式字符串string变为字符串pre_expr*//*后调用reversal_string()函数反转得到前缀表达式pre_expr*/Status ReadInorderExpr(char *string,char *PreExpr){int i,j,len,CharNumber=1;/*len表示字符串string的长度,char_number是记录数组save_number[]的个数*/int number;/*保存大于9的常量*/InitStack1(S);/*初始栈*/Push1(S,'#');/*先将字符'#'入栈,用来表示作为栈的最底一个元素*/len=strlen(string);/*len为字符串string的长度*/c=string[len-1];/*从字符串的最后一个字符开始向前扫描*/i=len-1;while(!StackEmpty1(S)&&i>=0){/*栈不为空且i大于等于0*/if(c=='('){/*字符为'('*/Pop1(S,c);/*出栈,赋值给c*/while(c!=')'){/*假如c不为')',出栈*/*PreExpr++=c;if(!StackEmpty1(S)&&GetTop1(S,c1)&&c1!='#') Pop1(S,c);else {cout<<"\n输入的表达式有误!";return ERROR;}}}else if(c==')'){Push1(S,c);} /*字符为')',入栈*/else if(c>='0'&&c<='9'){/*字符为'0'-'9'之间,循环扫描string前一个字符,后确定常量的大小*/number=c-'0';/*number为第一个常量字符的ASCII码-48*/for(c1=string[i-1],j=1;(c1>='0'&&c1<='9')&&i>=0;j++,i--){/*循环扫描string前一个字符,求出常量后赋给number*/number=(c1-'0')*pow(10,j)+number;/*number为扫描到的常量*/c1=string[i-2];}SaveNumber[CharNumber]=number;/*将number存入到数组save_number中,下标为char_number*/*PreExpr++=c;CharNumber++;}else if((c>='a'&&c<='z')||(c>='A'&&c<='Z')){//string下一个字符不能为常量或变量,否则,出错if((string[i-1]>='0'&&string[i-1]<='9')||(string[i-1]>='A'&&string[i-1]<='Z')||(string[i-1]>='a'&&string[i-1]<='z')) {cout<<("\n输入的表达式有误!");return ERROR;}else *PreExpr++=c;}else if(c=='*'||c=='/'){/*字符为运算符'*'或'/'*/while(GetTop1(S,c1)&&(c1=='^')){Pop1(S,c1);*PreExpr++=c1;}/*如果c1比c优先,出栈*/Push1(S,c);/*入栈字符c*/}else if(c=='+'||c=='-'){/*字符为运算符'+'或'-'*/while(GetTop1(S,c1)&&(c1=='^'||c1=='*'||c1=='/')){Pop1(S,c1);*PreExpr++=c1;}/*如果c1比c优先,出栈*/Push1(S,c);/*入栈运算符c*/}else if(c=='^'){Push1(S,c);/*入栈运算符'^'*/}else {cout<<"\n输入的表达式有误!";return ERROR;}/*其他字符,错误,返回ERROR*/i--;/*下一个字符*/if(i>=0) c=string[i];/*i不小于0,c=string[i]循环下一个字符*/else /*否则,将清空栈*/while(!StackEmpty1(S)&&GetTop1(S,c1)&&c1!='#') {Pop1(S,c);*PreExpr++=c;} }Pop1(S,c);/*将'#'出栈*/*PreExpr='\0';/*字符串结束符*/if(i<0&&StackEmpty1(S)) return OK;else return ERROR;}/*将字符串exprstring反转过来*/void ReversalString(char *exprstring){len=strlen(exprstring);/*len为exprstring的长度*/for(i=0,j=len-1;i<j;i++,j--){/*字符串前后两个字符对换*/temp=exprstring[i];exprstring[i]=exprstring[j];exprstring[j]=temp;}}/*常数合并操作函数,合并表达式E中所有常数运算*/void MergeConst(BiTree *E){while((*E)->lchild&&(*E)->rchild){/*左右孩子不为空*/if((*E)->lchild->data.tag==INT&&(*E)->rchild->data.tag==INT){//假如左右孩子为常量,合并result=Operate((*E)->lchild->data.num,(*E)->data.c,(*E)->rchild->data.num);/*常数合并运算,调用Operate()函数求值*/(*E)->data.tag=INT;(*E)->data.num=result;/*修改之前的运算符为常量*/free((*E)->lchild);/*释放左孩子*/free((*E)->rchild);/*释放右孩子*/(*E)->lchild=(*E)->rchild=NULL;/*左右孩子置空*/}else{MergeConst(&((*E)->lchild));/*递归左孩子*/MergeConst(&((*E)->rchild));/*递归右孩子*/}}}//判断是否操作符int IsOperator(char c){switch(c){case '+': return TRUE;case '-': return TRUE;case '*': return TRUE;case '/': return TRUE;case '^': return TRUE;default: return FALSE;}}void Diff(BiTree &E,char v)//求偏导数{if((E->lchild)&&(E->rchild))//树不为空{if((E->rchild->data.c=='^')&&(E->rchild->lchild->data.c==v) )//若该变量为要求偏导的变量,则对其求偏导{E->lchild->data.num=(E->lchild->data.num)*(E->rchild->rchild->data.num);E->lchild->data.tag=INT;E->rchild->rchild->data.num=E->rchild->rchild->data.num-1;}else if(E->rchild->data.tag==INT&&(E->data.c=='+'||E->data.c=='-'))//若该变量不是要求偏导的变量,且为整数,则以0替换其中数据{E->rchild->data.num=0;E->rchild->data.tag=INT;}else if((E->rchild->data.c==v)&&(IsOperator(E->lchild->data.c)))//否则以1替换其中数据{E->rchild->data.num=1;E->rchild->data.tag=INT;}else if((E->rchild->data.c==v)&&E->lchild->data.tag==INT){E->data.num=E->lchild->data.num;E->data.tag=INT;free(E->lchild);free(E->rchild);E->lchild=E->rchild=NULL;}Diff(E->lchild,v);//递归执行左子树Diff(E->rchild,v);//递归执行右子树}else return;}3.主程序和其他函数:char menu()//主菜单{char choice;cout<<"\n\t****************************************";cout<<"\n\t***********9.表达式类型的实现***********";cout<<"\n\t 1 >>>输入正确的前缀表达式";cout<<"\n\t 2 >>>带括弧的中缀表示式输出";cout<<"\n\t 3 >>>对变量进行赋值";cout<<"\n\t 4 >>>对算数表达式求值";cout<<"\n\t 5 >>>构造一个新的复合表达式";cout<<"\n\t 6 >>>以表达式的原书写形式输入(选作)";cout<<"\n\t 7 >>>合并表达式中所有常数运算(选作)";cout<<"\n\t 8 >>>三角函数操作 (选作)";cout<<"\n\t 9 >>>求偏导数 (选作)";cout<<"\n\t 0 >>>退出";cout<<"\n\t****************************************";cout<<"\n\t请输入你的选择(数字)>>>>>";cin >> choice;return choice;}int main(){BiTree E,E1;//两个表达式E和E1int flag=0;//表达式E构造标志,为0表示未构造,为1表示已构造char V,P;//V被赋值,P为符合表达式运算符char string[30],ExprString[30];//字符串while(TRUE){system("cls");//清屏switch(menu()) {case '1':/*1 >>>输入正确的前缀表达式*/cout<<"\n\t*************************输入提示信息************************";cout<<"\n\t输入正确的前缀表达式的要求:";cout<<"\n\t\t【变量】 a-z或A-Z";cout<<"\n\t\t【常量】 0-9,不能超过9";cout<<"\n\t\t【运算符】 +,-,*,/,^";cout<<"\n\t请输入正确的前缀表达式,后按回车键存入缓冲区,否则可能会出错!";cout<<"\n\t*************************************************************";if(InputExpr(ExprString,0))//在flag=0时,初始输入if(ReadExpr(&E,ExprString)){//前缀读入并构造Eflag=1;cout<<"\n表达式构造成功!请按任意键返回菜单";}getchar();break;case '2':/*2 >>>带括弧的中缀表示式输出*/if(flag==1){cout<<("\n\t带括弧的中缀表达式为:");WriteExpr(E);}else cout<<("\n\t表达式未构造成功!请重新构造成功的表达式!");getchar();getchar();break;case '3':/*3 >>>对变量进行赋值*/cout<<("\n\t********************赋值操作说明信息***********************************");cout<<("\n\t赋值操作:实现对表达式中的某一个变量V的赋值,即使V=C,C为一整数");cout<<("\n\t 【1】根据输出的表达式,输入要赋值的变量V,只能输入一个字符,否则出错");cout<<("\n\t 【2】输入要将变量V赋值为的整数C,只能是整数,否则出错");cout<<("\n\t 【注】如果表达式未构造,请回到主菜单选择构造表达式");cout<<("\n\t***********************************************************************");if(flag==1){int AssignFlag=0;cout<<"\n表达式E为:";WriteExpr(E);fflush(stdin);/*清理缓冲区*/cout<<"\n请输入要赋值的字符:";V=getchar();cout<<"请输入要将赋值为:";cin>>c;Assign(&E,V,c,&AssignFlag);//赋值并改变标志if(AssignFlag){cout<<"\n赋值成功!\n赋值后的表达式为:";WriteExpr(E);}else cout<<"\n表达式里没有%c这个变量!",V;}else cout<<"\n表达式未构造成功!请构造成功的表达式!";getchar();getchar();break;case '4':/*4 >>>对算数表达式求值*/cout<<"\n\t********************算数表达式求值说明信息************************";cout<<"\n\t 【注】如果表达式还有变量未赋值,即表达式不是算数表达式";cout<<"\n\t 不能求出表达式的值,请回到主菜单选择赋值操作,后再求值";cout<<"\n\t******************************************************************";if(flag==1){cout<<"\n算数表达式:";WriteExpr(E);if(Check(E)){ //检查是否全赋值result=Value(E);cout<<"\n求算数表达式的值:\t";WriteExpr(E);cout<<"="<<result;}}else cout<<"\n表达式未构造成功!请构造成功的表达式!";getchar();getchar();break;case '5':/*5 >>>构造一个新的复合表达式*/cout<<"\n\t*****************构造新的复合表达式说明信息***************************";cout<<"\n\t 【1】构造一个新的表达式E1,采用表达式的原书写形式输入";cout<<"\n\t 【2】构造表达式E1成功后,输入要复合表达式E和E1的操作运算符(+,-,*,/,^)";cout<<"\n\t 【注】如表达式E未构造,不能复合表达式;如构造表达式E1错误,复合失败";cout<<"\n\t***********************************************************************";if(flag==1){cout<<"\n表达式E1为:";WriteExpr(E);cout<<"\n请构造新的表达式E2:";fflush(stdin);/*清理缓冲区*/if(InputExpr(string,1)){//标志为1,输入字符串if(ReadInorderExpr(string,ExprString)){//入栈ReversalString(ExprString);//反转if(ReadExpr(&E1,ExprString)){flag=1;cout<<("\n表达式E2构造成功!");WriteExpr(E1);cout<<("\n请输入要构造新的复合表达式的操作运算符>>>");P=getchar();while(P!='*'&&P!='/'&&P!='+'&&P!='-'&&P!='^'){fflush(stdin);/*清理缓冲区*/cout<<"\n输入的操作运算符有误!请重新输入>>>";P=getchar();}CompoundExpr(P,E,E1);}else cout<<"\n复合新的表达式失败!请按任意键返回主菜单!";}}}else cout<<"\n表达式未构造成功!请构造成功的表达式!";getchar();getchar();break;case '6':/*6 >>>以表达式的原书写形式输入*/cout<<"\n\t*************以表达式的原书写形式输入说明信息************************";cout<<"\n\t输入正确的原书写形式表达式";cout<<"\n\t 【变量】 a-z或A-Z";cout<<"\n\t 【常量】大于等于0的正整数";cout<<"\n\t 【运算符】 +,-,*,/,^(乘幂)";cout<<"\n\t 【括弧】左括弧 ( ,右括弧 ) ";cout<<"\n\t 【注】表示式中常量最多只能是30个,超过30个,出错!";cout<<"\n\t按原书写形式输入中,请按照正确的方式输入,否则可能会出错!";cout<<"\n\t**********************************************************************";if(InputExpr(string,1))if(ReadInorderExpr(string,ExprString)){ReversalString(ExprString);if(ReadExpr(&E,ExprString)){flag=1;cout<<"\n表达式构造成功!\n输入的带括弧的中缀表达式:";WriteExpr(E);}}getchar();getchar();break;case '7':/*7 >>>合并表达式中所有常数运算*/cout<<"\n***************合并表达式中的所有常数运算*******************************";cout<<"\n 【注】合并表达式中的所有常数运算并不能一次性将常数都合并!";cout<<"\n例如:表达式'1+2*(3+3*4+9/3)'的常数合并,选择7进行合并,结果变为\n'1+2*(3+12+3)',";cout<<"根据优先级先后合并的,如果要合并到最后,需多次选择7\n进行合并,又合并一次'1+2*(15+3)',";cout<<"再次合并'1+2*18',再次合并'1+36',\n再次合并'37',后无法合并!";cout<<"\n************************************************************************";if(flag==1) {cout<<"\n原表达式为:";WriteExpr(E);MergeConst(&E);//常数合并操作cout<<"\n合并表达式中所有的常数运算后的表达式:";WriteExpr(E);}else cout<<"\n表达式未构造成功!请构造成功的表达式!";getchar();getchar();break;case '8'://三角函数操作cout<<"\t***************************三角函数操作(选作)***************************";cout<<"\n";cout<<"\n\t[注] 请按要求输入其中 s代表sin c代表cos t代表tan ";cout<<"\n\t角度用弧度表示,例如~1 即表示sin 1";cout<<"\n\t本操作只可求三角函数值,如需其他操作请将结果带入其它操作中";cout<<"\n\t输入一个字符请按回车,确保正确录入";cout<<"\n\t************************************************************************";double opr1,result1;char opr;cout<<"\n请按要求输入";cin>>opr;cin>>opr1;result1=Operate1(opr,opr1);cout<<"结果为:"<<result1;getchar();getchar();break;case '9'://求导getchar();char h;cout<<"输入需要求偏导的变量字符\n";cin>>h;Diff(E,h);WriteExpr(E);getchar();getchar();break;case '0':/*0 >>>退出*/cout<<"\n请按任意键退出!";getchar();getchar();exit(0);break;default :cout<<"\n输入有误!请按任意键回到主菜单重新选择!";getchar();getchar();getchar();//Sleep(5000);break;}}return 0;}(部分代码较长,故在word文档中较难整理格式,请参见附录源代码查看)函数调用关系:四.调试分析1.合并表达式所有常数运算功能一开始只能实现一次合并,即:1+4*6=1+24 或者8+3*2^4=8+3*16。

数据结构实验代码

数据结构实验代码

《数据结构》实验代码实验一:针对链式或顺序存储的线性表实现指定的操作题1 问题描述:有两个指数递减的一元多项式,写一程序先求这两个多项式的和,再求它们的积。

基本要求:用带表头结点的单链表作为多项式的存储表示;要建立两个单链表;多项式相加就是要把一个单链表中的结点插入到另一个单链表中去,要注意插入、删除操作中指针的正确修改。

题2 问题描述:编号为1,2,···,n的n个人围坐在一圆桌旁,每人持有一个正整数的密码。

从第一个人开始报数,报到一个预先约定的正整数m时,停止报数,报m的人退席,下一个人又重新从1开始报数,依此重复,直至所有的人都退席。

编一程序输出他们退席的编号序列。

例如,设m=20,n=7,7个人的密码依次是3,1,7,2,4,8,4,则退席的人的编号依次为6,1,4,7,2,3,5。

基本要求:用不带表头结点的循环单链表表示围成圆圈的n个人;要求建立此循环单链表;某人离席相当于删除一个结点,要正确设置程序中循环终止的条件和删除结点时指针的修改变化。

//实验1.1代码#include<iostream>using namespace std;struct poNode{float coef;int expn;poNode *next;};class Polynomail{public:Polynomail(int m=0);~Polynomail();int Print();int PolynLength();Polynomail &AddPolyn(Polynomail &P2,Polynomail &P3);Polynomail &MultiplyPolyn(Polynomail &P2,Polynomail &P4);private:int InsertpoNode();poNode *first;};int main(){int m;cout<<"输入多项式P1项数"<<endl;cin>>m;Polynomail P1(m);if(P1.PolynLength()!=m){cout<<"error!"<<endl;return -1;}cout<<"输入多项式P2项数"<<endl;cin>>m;Polynomail P2(m);if(P2.PolynLength()!=m){cout<<"error!"<<endl;return -1;}cout<<"多项式P1:";P1.Print();cout<<"多项式P2:";P2.Print();Polynomail P3;P3=P1.AddPolyn(P2,P3);cout<<"P1+P2:";P3.Print();Polynomail P4;P4=P1.MultiplyPolyn(P2,P4);cout<<"P1*P2:";P4.Print();return 0;}int Polynomail::InsertpoNode() { if(first==NULL){first=new poNode;cout<<"输入系数和指数:"<<endl;cin>>first->coef;cin>>first->expn;first->next=NULL;}else{poNode *p=new poNode;poNode *q=first;cout<<"输入系数和指数:"<<endl; cin>>p->coef;cin>>p->expn;poNode *r;while(q->next!=NULL&&q->expn<p->expn) {r=q;q=q->next;}if(q==first&&q->next!=NULL){if(q->expn==p->expn){return -1;}p->next=q;first=p;}else if(q==first&&q->next==NULL){if(p->expn<q->expn){p->next=q;first=p;}else if(p->expn>q->expn){q->next=p;p->next=NULL;}else{return -1;}}else if(q->next==NULL&&q!=first&&p->expn>q->expn) {q->next=p;p->next=NULL;}else{if(q->expn==p->expn){return -1;}r->next=p;p->next=q;}}return 0;}Polynomail::Polynomail(int m){first=NULL;int i;for(i=0;i<m;i++){int r=InsertpoNode();if(r==-1) break;}}int Polynomail::Print(){poNode *p=first;cout<<"f(x)=";if(first==NULL) cout<<"NULL"<<endl;while(p!=NULL){cout<<p->coef<<"*x^"<<p->expn;if(p->next==NULL) cout<<endl;else cout<<"+";p=p->next;}return 0;}Polynomail::~Polynomail(){poNode *p=first;while(p!=NULL){p=p->next;delete first;first=p;}}int Polynomail::PolynLength(){int i=0;poNode *p=first;while(p!=NULL){p=p->next;i++;}return i;}Polynomail &Polynomail::AddPolyn(Polynomail &P2,Polynomail &P3) {poNode *p=first;poNode *q=P2.first;P3.first=new poNode;poNode *r=P3.first;while(p!=NULL&&q!=NULL){if(p->expn==q->expn){r->coef=p->coef+q->coef;r->expn=p->expn;p=p->next;q=q->next;}else if(p->expn<q->expn){r->coef=p->coef;r->expn=p->expn;p=p->next;}else{r->coef=q->coef;r->expn=q->expn;q=q->next;}if(p!=NULL||q!=NULL){r->next=new poNode;r=r->next;}else r->next=NULL;}while(p!=NULL||q!=NULL) {if(p!=NULL){r->coef=p->coef;r->expn=p->expn;p=p->next;}else{r->coef=q->coef;r->expn=q->expn;q=q->next;}if(p!=NULL||q!=NULL){r->next=new poNode;r=r->next;}else r->next=NULL;}return P3;}Polynomail &Polynomail::MultiplyPolyn(Polynomail &P2,Polynomail &P4){poNode *p=first;while(p!=NULL){Polynomail P3;poNode *q=P2.first;P3.first=new poNode;poNode *r=P3.first;r->coef=p->coef*q->coef;r->expn=p->expn+q->expn;q=q->next;while(q!=NULL){r->next=new poNode;r=r->next;r->coef=p->coef*q->coef;r->expn=p->expn+q->expn;q=q->next;}r->next=NULL;P4=P4.AddPolyn(P3,P4);p=p->next;}return P4;}//实验1.2代码#include<iostream>using namespace std;struct numNode{int key;int num;numNode *next;};int CreatCircleList(numNode *now,int length); int Loop(numNode *now,int m);int main(){int m;int n;numNode *now=new numNode;cout<<"请输入人数:"<<endl;cin>>n;cout<<"请输入初始数m:"<<endl;cin>>m;CreatCircleList(now,n);Loop(now,m);return 0;}int CreatCircleList(numNode *now,int length){if(length<=0){cout<<"error!"<<endl;return -1;}now->num=1;cout<<"请输入编号为1的人拥有的密码。

数据结构实验总结及源代码

数据结构实验总结及源代码

实验1 线性表1 问题描述:使用线性表实现一个通讯录,通讯录内容有:学号、姓名、电话号码。

使其完成以下功能。

(1)建立一个通讯录(2)插入一个数据元素(3)删除一个元素,返回其值(4)结束程序请写出基本的算法思想,以及源程序代码。

实验2 括号匹配问题描述编写一程序判断从键盘输入的子符串括号是否匹配。

假设需判断的括号只有“(”,“)”,“[”,“]”四种。

实验4 病人看病模拟程序【问题描述】编写一个程序,反映病人到医院看病,排队看医生的情况。

在病人排队的过程中,主要重复两件事:(1)病人到达诊室,将病历本交给护士,排到等待队列中候诊。

(2)护士从等待队列中取出下一位病人的病历,该病人进入诊室就诊。

要求模拟病人等待就诊这一过程。

程序采用菜单方式,其选项及功能说明如下:(1)排队――输入排队病人的病历号,加入病人排队队列中。

(2)就诊――病人排队队列中最前面的病人就诊,并将其从队列中删除;(3)查看排队――从对首到队尾列出所有的排队病人的病历号;(4)不再排队,余下一次就诊――从对首到队尾列出所有的排队病人的病历号,并退出运行;(5)下班――退出运行;线性表实验源代码#include <iostream.h>#include <conio.h>#include <iomanip.h>#include <string.h>//--------------------------------------------------------------------struct ElemType // 数据元素的类型{ int numb;char name[20];long tel;};const int MAXSIZE=100; // 数组的容量class Sqlist{ private:ElemType elem[MAXSIZE]; //结构体的数组int length;public:Sqlist( void);~Sqlist(){ };void SetData(); //建立通讯录;void Insert( int i, ElemType e); //在位置i,插入一条记录ElemType Delet(int i); //删除位置i 的记录void PrintOut(); //打印结果};//-------------------------------------------------------------//Sqlist::Sqlist( ) { length=0;}//Sqlist::Sqlist( ) { length=0;}Sqlist::Sqlist(){length=0;}void Sqlist::SetData( ) //初步建立一个通讯录{ cout<<"\n 输入人数length="; cin>>length;for(int i=0;i<length;i++){ cout<<"\n 输入学号:"; cin>>elem[i].numb;cout<<"\n 输入姓名:"; cin>> elem[i].name;cout<<"\n 输入电话号:="; cin>>elem[i].tel;}}void Sqlist::Insert( int i, ElemType e){ int j; i--;if(i<0||i>length) cout<< " i Error!"<<endl;else { for(j=length+1; j>i; j--) elem[j]=elem[j-1];// for(j=length; j>i; j--) elem[j]=elem[j-1];elem[i]=e; length++;}}ElemType Sqlist::Delet(int i){ElemType x; int j; i--;if(i<0||i>length-1){ cout<< " i Error!"<<endl; x.numb=-1;} else { x=elem[i];for(j=i; j<length-1; j++) elem[j]=elem[j+1];//for(j=i; j<length; j++) elem[j]=elem[j+1];length--;}return x;}void Sqlist::PrintOut() //输出{ cout<<"\n 通讯录总人数:"<<length;cout<<"\n PrintOut Data:\n";cout<<setw(16)<<"学号"<<setw(20)<<"姓名"<<setw(20)<<"电话号"<<endl; ;for(int k=0; k<length;k++){ cout<<setw(16)<<elem[k].numb<<setw(20)<<elem[k].name<<setw(20)<<elem[k].tel<<cou t<<endl;}}//--------------------------------------------------int main( ){ int i,k; ElemType e,x;Sqlist as;cout<<"\n 通讯录演示";do{cout<<"\n\n";cout<<"\n\n 1. 初步建立一个通讯录(线性表)";cout<<"\n\n 2. 插入一个数据元素";cout<<"\n\n 3. 删除一个元素,返回其值";cout<<"\n\n 4. 结束程序";cout<<"\n********************************";cout<<"\n 请输入你的选择(1,2,3,4)"; cin>>k;switch(k){ case 1:{ as.SetData(); as.PrintOut(); }break;case 2:{ cout<<"\n 插入的位置,i=?"; cin>>i;cout<<"\n 插入的数据编号=?"; cin>>e.numb;cout<<"\n 插入的数据姓名=?"; cin>>;cout<<"\n 插入的数据电话号=?"; cin>>e.tel;as.Insert(i,e); as.PrintOut();}break;case 3:{ cout<<"\n 删除第几个元i=?"; cin>>i;x=as.Delet(i);cout<<"\n 被删除的元素数值= "<<setw(10)<<x.numb<<setw(10)<<<<setw(10)<<x.tel;as.PrintOut();}break;default:break;} //switch}while(k>=1&&k<4);cout<<"\n 再见!"; cout<<"\n 按任意键,返回。

数据结构c语言版实验及源代码

数据结构c语言版实验及源代码

实验1 求两个多项式的相加运算(线性表)编写一个程序用单链表存储多项式,并实现两个多项式相加的函数。

/*文件名:实验1.cpp*/#include <stdio.h>#include <malloc.h>#define MAX 20 /*多项式最多项数*/typedef struct /*定义存放多项式的数组类型*/{float coef; /*系数*/int exp; /*指数*/} PolyArray[MAX];typedef struct pnode /*定义单链表结点类型*/{float coef; /*系数*/int exp; /*指数*/struct pnode *next;} PolyNode;void DispPoly(PolyNode *L) /*输出多项式*/{PolyNode *p=L->next;while (p!=NULL){printf("%gX^%d ",p->coef,p->exp);p=p->next;}printf("\n");}void CreateListR(PolyNode *&L,PolyArray a,int n) /*尾插法建表*/{PolyNode *s,*r;int i;L=(PolyNode *)malloc(sizeof(PolyNode)); /*创建头结点*/L->next=NULL;r=L; /*r始终指向终端结点,开始时指向头结点*/ for (i=0;i<n;i++){s=(PolyNode *)malloc(sizeof(PolyNode));/*创建新结点*/s->coef=a[i].coef;s->exp=a[i].exp;r->next=s; /*将*s插入*r之后*/r=s;}r->next=NULL; /*终端结点next域置为NULL*/}void Sort(PolyNode *&head) /*按exp域递减排序*/{PolyNode *p=head->next,*q,*r;if (p!=NULL) /*若原单链表中有一个或以上的数据结点*/ {r=p->next; /*r保存*p结点后继结点的指针*/p->next=NULL; /*构造只含一个数据结点的有序表*/p=r;while (p!=NULL){r=p->next; /*r保存*p结点后继结点的指针*/q=head;while (q->next!=NULL && q->next->exp>p->exp)q=q->next; /*在有序表中找插入*p的前驱结点*q*/ p->next=q->next; /*将*p插入到*q之后*/q->next=p;p=r;}}}void Add(PolyNode *ha,PolyNode *hb,PolyNode *&hc) /*求两有序集合的并*/ {PolyNode *pa=ha->next,*pb=hb->next,*s,*tc;float c;hc=(PolyNode *)malloc(sizeof(PolyNode)); /*创建头结点*/tc=hc;while (pa!=NULL && pb!=NULL){if (pa->exp>pb->exp){s=(PolyNode *)malloc(sizeof(PolyNode)); /*复制结点*/s->exp=pa->exp;s->coef=pa->coef;tc->next=s;tc=s;pa=pa->next;}else if (pa->exp<pb->exp){s=(PolyNode *)malloc(sizeof(PolyNode)); /*复制结点*/s->exp=pb->exp;s->coef=pb->coef;tc->next=s;tc=s;pb=pb->next;}else /*pa->exp=pb->exp*/{c=pa->coef+pb->coef;if (c!=0) /*系数之和不为0时创建新结点*/{s=(PolyNode *)malloc(sizeof(PolyNode)); /*复制结点*/s->exp=pa->exp;s->coef=c;tc->next=s;tc=s;}pa=pa->next;pb=pb->next;}}if (pb!=NULL) pa=pb; /*复制余下的结点*/while (pa!=NULL){s=(PolyNode *)malloc(sizeof(PolyNode)); /*复制结点*/s->exp=pa->exp;s->coef=pa->coef;tc->next=s;tc=s;pa=pa->next;}tc->next=NULL;}void main(){PolyNode *ha,*hb,*hc;PolyArray a={{1.2,0},{2.5,1},{3.2,3},{-2.5,5}};PolyArray b={{-1.2,0},{2.5,1},{3.2,3},{2.5,5},{5.4,10}};CreateListR(ha,a,4);CreateListR(hb,b,5);printf("原多项式A: ");DispPoly(ha);printf("原多项式B: ");DispPoly(hb);Sort(ha);Sort(hb);printf("有序多项式A: ");DispPoly(ha);printf("有序多项式B: ");DispPoly(hb);Add(ha,hb,hc);printf("多项式相加: ");DispPoly(hc);}实验2 求解迷宫问题的所有路径 及最短路径程序(堆栈) 改进教材中3.2.4节中的求解迷宫问题程序,要求输出如图所示的迷宫的所有路径,并求出最短路径成都及最短路径。

数据结构与算法实验源代码

数据结构与算法实验源代码

实验二#include<stdio.h>#include<stdlib.h>#define Maxlen 100typedef struct{int data[Maxlen];int last;}Sequenlist;Sequenlist *SqLsetnull(){ //建立一个空的顺序表Sequenlist *L;L=(Sequenlist *)malloc(sizeof(Sequenlist));L->last=-1;return L;}void *SqLset(Sequenlist *L){ //对顺序表输入数据int n;printf("请输入要输入的元素数量:");scanf("%d",&n);printf("请输入要输入的元素:");for(int i=0;i<n;i++){scanf("%d",&L->data[i]);}L->last=i;return L;}int SqLdelete(Sequenlist *L,int i){ //删除顺序表中的元素//因为只是调用该函数删除顺序表中多余的元素省略的一些数据判断int j;for(j=i;j<=L->last+1;j++)L->data[j]=L->data[j+1];L->last--;return 1;}void SqLdel(Sequenlist *L){ //寻找顺序表中多余的元素并删除int i,j;if(L->last<0){printf("\n顺序表为空\n");}else{for(i=0;i<=L->last;i++){for(j=i+1;j<=L->last;j++)if(L->data[j]==L->data[i]){SqLdelete(L,j); //调用函数删除下标为j的结点}}}}void SqLsc(Sequenlist *L){ //输出顺序表中的数据int i;if(L->last<0)printf("\n顺序表为空\n");else{printf("顺序表中的元素:");for(i=0;i<L->last;i++){printf("%d ",L->data[i]);}}printf("\n");}int main(void){Sequenlist *L;L=SqLsetnull();int choice;printf("1,输入数据2,删除重复多余的数据3,输出数据0,退出\n");do{printf("请输入选择:");scanf("%d",&choice);switch(choice){case 1:SqLset(L);printf("\n");break;case 2:SqLdel(L);printf("\n");break;case 3:SqLsc(L);printf("\n");break;default:printf("请输入正确的选择!\n");break;case 0:break;}}while(choice!=0);return 0;}实验三#include<stdio.h>#include<stdlib.h>#define SIZE 15typedef struct{int data[SIZE];int last;}RecordList;RecordList *shuru(){ //向顺序表中输入数据int s,i=0;RecordList *L;L=(RecordList *)malloc(sizeof(RecordList));printf("请输入要输入到顺序表中数据的数量:");scanf("%d",&s);if(s>15){printf("超过最大的数据长度");}else{printf("请输入要输入的数据:");for(i=0;i<s;i++)scanf("%d",&L->data[i]);}printf("成功输入%d个数据\n\n",i);L->last=i-1;return L;}void paixu(RecordList *L){ //冒泡排序法对顺序表中的数据进行排序int x,change=1,i,j;for(i=0;i<L->last&&change!=0;i++){change=0;for(j=0;j<L->last-i;j++){if(L->data[j]>L->data[j+1]){x=L->data[j+1];L->data[j+1]=L->data[j];L->data[j]=x;change=1;}}}}int BinSrch(RecordList *L,int k){ //二分查找int low=0,i=-1,high,mid;high=L->last;while(low<=high){mid=(low+high)/2;if(k==L->data[mid]){i=mid;break;}else if(k<L->data[mid])high=mid-1;elselow=mid+1;}return i;}int main(void){RecordList *L=NULL;int i,choice,data1;printf("1,输入数据2,二分法查找0,退出\n");do{printf("请输入选择:");scanf("%d",&choice);switch(choice){case 1:L=shuru(); //输入数据paixu(L); //数据排序break;case 2:if(L==NULL||L->last==-1){ //查找前检验表中是否有数据printf("\n顺序表为空\n\n");break;}else{printf("请输入要查找的数据:");scanf("%d",&data1);i=BinSrch(L,data1);printf("数据%d的序号(下标)是%d \n\n",data1,i);break;}default:printf("\n请输入正确的选择\n\n");break;case 0:break;}}while(choice!=0);return 0;}实验四#include<stdio.h>#include<stdlib.h>#define SIZE 15typedef struct{int data[SIZE];int last;}RecordList;RecordList *shuru(){ //向顺序表中输入数据int s,i=0;RecordList *L;L=(RecordList *)malloc(sizeof(RecordList));printf("请输入要输入到顺序表中数据的数量:");scanf("%d",&s);if(s>15){printf("超过最大的数据长度");}else{printf("请输入要输入的数据:");for(i=0;i<s;i++)scanf("%d",&L->data[i]);}printf("成功输入%d个数据\n\n",i);L->last=i-1;return L;}void paixu(RecordList *L){ //冒泡排序法对顺序表中的数据进行排序int x,change1=1,change2=1,i,j;for(i=0;change1!=0||change2!=0;i++){change1=0;change2=0;if(i%2==0){for(j=1;j<L->last;j=j+2){if(L->data[j]>L->data[j+1]){x=L->data[j+1];L->data[j+1]=L->data[j];L->data[j]=x;change1=1;}}}else{for(j=0;j<L->last;j=j+2){if(L->data[j]>L->data[j+1]){x=L->data[j+1];L->data[j+1]=L->data[j];L->data[j]=x;change2=1;}}}}}void shuchu(RecordList *L){int i;for(i=0;i<=L->last;i++){printf("%d ",L->data[i]);}}int main(void){RecordList *L=NULL;int choice;printf("1,输入数据2,冒泡排序3,输出0,退出\n");do{printf("请输入选择:");scanf("%d",&choice);switch(choice){case 1:L=shuru(); //输入数据break;case 2:paixu(L); //数据排序printf("排序成功\n\n");break;case 3:shuchu(L);printf("\n");break;default:printf("\n请输入正确的选择\n\n");break;case 0:break;}}while(choice!=0);return 0;}实验五#include<stdio.h>#include<stdlib.h>typedef struct node{int data;struct node *next;}LinkList;LinkList *CreatList(){LinkList *head,*r,*s; //建立带头结点的链表,head为链表的头结点int n;head=(LinkList *)malloc(sizeof(LinkList));head->next=NULL;r=head;printf("请输入要输入的数据的个数:");scanf("%d",&n);printf("请输入要输入的数据:");for(int i=0;i<n;i++){s=(LinkList *)malloc(sizeof(LinkList));scanf("%d",&s->data);s->next=NULL;r->next=s;r=s; //r指向链表的尾节点}return head;}void Add(LinkList *head,int x){LinkList *s,*r,*t;t=(LinkList *)malloc(sizeof(LinkList));r=head;s=head->next;for(;s!=NULL&&x>=s->data;s=s->next){ //要寻找要插入节点的位置r=r->next;}t->data=x;if(s==NULL){ //插入在链表的表尾r->next=t;t->next=NULL;}else{ //插入在链表的中间t->next=r->next;r->next=t;}}void Out(LinkList *head){ //输出表中的数据LinkList *L;L=head->next;printf("表中的数据:");for(;L;L=L->next){printf("%d ",L->data);}printf("\n");}int main(void){LinkList *head;int x;head=CreatList();Out(head);printf("请输入要插入的数据:");scanf("%d",&x);Add(head,x);Out(head);return 0;}实验七#include<stdio.h>#include<stdlib.h>typedef struct node{int data;struct node *next;}LinkList;typedef struct{LinkList *rear;}LinkQueue;LinkQueue *SetQueue(){ //建立空的队列LinkQueue *Q;LinkList *head;Q=(LinkQueue *)malloc(sizeof(LinkQueue));head=(LinkList *)malloc(sizeof(LinkQueue));head->data=-1;head->next=head;Q->rear=head;return Q;}int QueueEmpty(LinkQueue *Q){ //检验对列是否为空LinkList *p;p=Q->rear;if(p->data==-1){return 1;}elsereturn 0;}LinkQueue *Add(LinkQueue *Q,int x){ //数据入队LinkList *p;p=(LinkList *)malloc(sizeof(LinkList));p->data=x;p->next=Q->rear->next;Q->rear->next=p;Q->rear=p;return Q;}void Out(LinkQueue *Q){ //数据出队LinkList *p1,*p2;p1=Q->rear;p2=Q->rear;p2=p2->next;p1=p2->next;if(p1->data==-1){printf("队列为空");return;}printf("出队的数据是%d\n",p1->data);p2->next=p1->next;}LinkQueue *SetNull(LinkQueue *Q){ //队列置空Q->rear=Q->rear->next;Q->rear->next=Q->rear;return Q;}int main(void){LinkQueue *Q=NULL;int choice,x,i;printf("1,建立空队列2,数据入队3,数据出队4,置队空5,检验队空0,退出\n");do{printf("\n请输入选择:");scanf("%d",&choice);switch(choice){case 1:Q=SetQueue();printf("已建立空队列\n");break;case 2:printf("请输入要入队的数据:");scanf("%d",&x);Q=Add(Q,x);break;case 3:Out(Q);break;case 4:Q=SetNull(Q);printf("队列已置空");break;case 5:i=QueueEmpty(Q);if(i==1)printf("队列为空\n");elseprintf("队列未空\n");break;case 0:break;}}while(choice!=0);return 0;}实验八#include<stdio.h>#define SIZE 100void zhuanzhi(int sa[],int n){ //转置函数int m,t;for(int i=0;i<3*n-2;i++){if(i%3!=0){m=i+1;t=sa[i];sa[i]=sa[m]; //交换对称的两个数据sa[m]=t;i++; //跳过矩阵的下三角数据} //矩阵对角线上的数据不进行操作}}void JPrintf(int sa[],int n){ //输出函数int i,j;for(i=1;i<=n;i++){for(j=1;j<=n;j++){if(i==j-1||i==j||i==j+1){ //i==j-1 对角线下方的元素i==j对角线上的元素i==j+1对角线上方的元素printf(" %d",sa[2*i+j-3]);//非零元素在数据中的下标为2*i+j-3}elseprintf(" 0");}printf("\n");}}int main(void){int n,sa[SIZE];printf("请输入三对角矩阵的阶数:");scanf("%d",&n);printf("请依次输入三对角矩阵中的非零数据:");for(int i=0;i<3*n-2;i++){ //三对角矩阵共有3*n-2g个非零元素scanf("%d",&sa[i]);}JPrintf(sa,n);zhuanzhi(sa,n);printf("转置后的矩阵:\n");JPrintf(sa,n);return 0;}实验九#include<stdio.h>#include<stdlib.h>#define maxsize 10typedef struct node{char data;struct node *lchild,*rchild;}Bitree;Bitree *Q[maxsize]; //使用队列临时记录节点地址Bitree *Creatree(){ //建立一个二叉树char ch;int front,rear;Bitree *T,*s;T=NULL;front=1;rear=0;printf("请输入一个二叉树(以#号结束):");ch=getchar();while(ch!='#'){ //以输入“#”结束输入s=NULL;if(ch!='@'){ //输入“@”表示虚节点s=(Bitree *)malloc(sizeof(Bitree)); //如果不是虚节点就建立新节点s->data=ch;s->lchild=s->rchild=NULL;}rear++;Q[rear]=s;if(rear==1) //输入的第一个节点为根节点T=s;else{if(s!=NULL&&Q[front]!=NULL)if(rear%2==0) //若rear为偶数则该节点为父节点的左孩子,否则为右孩子Q[front]->lchild=s;elseQ[front]->rchild=s;if(rear%2==1)front++;}ch=getchar();}return T;}void visite(Bitree *T,int *m){if(T->lchild==NULL&&T->rchild==NULL){ //没有左孩子也没有右孩子就是叶子节点(*m)++;}}void Preorder(Bitree *T,int *m){ //使用递归遍历二叉树if(T){visite(T,m); //访问根节点Preorder(T->lchild,m);Preorder(T->rchild,m);}}int main(void){int *m,n=0;m=&n; //使用一个指针用于记录叶子节点的个数Bitree *T;T=Creatree();Preorder(T,m);printf("该二叉树的叶子节点数:%d\n",n);return 0;}实验十#include<stdio.h>#include<stdlib.h>#define maxsize 10typedef struct node{char data;struct node *lchild,*rchild;}Bitree;Bitree *Q[maxsize]; //使用队列临时记录节点地址Bitree *Creatree(){ //建立一个二叉树char ch;int front,rear;Bitree *T,*s;T=NULL;front=1;rear=0;printf("请输入一个二叉树(以#号结束):");ch=getchar();while(ch!='#'){ //以输入“#”结束输入s=NULL;if(ch!='@'){ //输入“@”表示虚节点s=(Bitree *)malloc(sizeof(Bitree)); //如果不是虚节点就建立新节点s->data=ch;s->lchild=s->rchild=NULL;}rear++;Q[rear]=s;if(rear==1) //输入的第一个节点为根节点T=s;else{if(s!=NULL&&Q[front]!=NULL)if(rear%2==0) //若rear为偶数则该节点为父节点的左孩子,否则为右孩子Q[front]->lchild=s;elseQ[front]->rchild=s;if(rear%2==1)front++;}ch=getchar();}return T;}void visite(Bitree *T,char m[]){ //把中序遍历的数据保存到数据m中int i=0;while(m[i]!='*'){ // * 是数组的结束标志i++;}m[i]=T->data;m[i+1]='*';}void Inorder(Bitree *T,char m[]){ //中序遍历递归算法if(T){Inorder(T->lchild,m);visite(T,m);Inorder(T->rchild,m);}}int Pan(char m[]){int i=0,j=0; //j==0是表示是二叉树while(m[i+1]!='*'){if(m[i]>m[i+1]){j=1; //j==1是表示不是二叉树break;}i++;}return j;}int main(void){Bitree *T;int j;T=Creatree();char m[50];m[0]='*';Inorder(T,m);j=Pan(m);if(j==1){printf("该二叉树不是二叉排序树\n");}elseprintf("该二叉树是二叉排序树\n");return 0;}实验十一#include<stdio.h>#include<stdlib.h>#include<iostream.h>#define MAX_VERTEX_NUM 100/* 临接表的数据类型定义*/typedef struct node{int adjvex; //邻接点位置struct node *nextarc; //指向下一个结点char info; //边得信息}ARCNODE;typedef struct VEXNODE{char vexdata; //顶点信息ARCNODE *firstarc; //指向第一个邻接点}VEXNODE,AdjList[MAX_VERTEX_NUM];typedef struct{ //邻接表类型AdjList vextices;int vexnum,arcnum; //顶点数目,边数目}ALGraph;ALGraph create_AdjListGraph(){ //建立邻接表int n,e,i,j,k;ALGraph alg;ARCNODE *p,*q;printf("请输入顶点数:");scanf("%d",&n);for(i=0;i<=n;i++){ //初始化邻接表alg.vextices[i].vexdata=(char)i;alg.vextices[i].firstarc=NULL;}printf("请输入边数:");scanf("%d",&e);printf("请输入图的信息:\n");for(i=0;i<e;i++){ //建立无向图的邻接表scanf("%d%d",&j,&k); //输入边的信息p=(ARCNODE *)malloc(sizeof(ARCNODE));p->adjvex=k;p->info=' ';p->nextarc=alg.vextices[j].firstarc; //把节点接到链表上alg.vextices[j].firstarc=p;q=(ARCNODE *)malloc(sizeof(ARCNODE));q->adjvex=j;q->info=' ';q->nextarc=alg.vextices[k].firstarc; //把节点接到链表上alg.vextices[k].firstarc=q;}alg.vexnum=n;alg.arcnum=e;return alg;}/* 邻接矩阵的数据类型定义*/typedef struct{int num; //顶点序号char data; //顶点数据}VERTEX;typedef struct{ //邻接矩阵类型int n; //顶点数目int e; //边的数目VERTEX vexs[MAX_VERTEX_NUM]; //存储顶点int edges[MAX_VERTEX_NUM][MAX_VERTEX_NUM];//邻接矩阵,存储边}MGraph;MGraph *ALG_MG(ALGraph alg){ //邻接表转化为邻接矩阵MGraph *mg;ARCNODE *arc;mg=(MGraph *)malloc(sizeof(MGraph));mg->n=alg.vexnum;mg->e=alg.arcnum;int i,j;for(i=0;i<=alg.vexnum;i++) //初始化邻接矩阵for(j=0;j<=alg.vexnum;j++){mg->edges[i][j]=0;}for(i=1;i<=alg.vexnum;i++){mg->vexs[i].num=i; //依次从邻接表中把顶点信息读入到邻接矩阵中mg->vexs[i].data=alg.vextices[i].vexdata;arc=alg.vextices[i].firstarc;for(;arc!=NULL;arc=arc->nextarc){ //从邻接表中把边得信息读入到邻接矩阵中mg->edges[i][arc->adjvex]=1;}}return mg;}void Palg(ALGraph G){ //输出邻接表int i,j;ARCNODE *p;printf("输出图为:\n");for(i=1;i<=G.vexnum;i++){p=G.vextices[i].firstarc;j=0;while(p!=NULL){printf("(%d,%d)",i,p->adjvex);p=p->nextarc;j=1;}if(j==1)cout<<endl;}}void Pmg(MGraph *mg){ //输出邻接矩阵for(int i=1;i<=mg->n;i++){ //遍历邻接矩阵for(int j=1;j<=mg->n;j++){printf("%d ",mg->edges[i][j]);}printf("\n");}}int main(void){ALGraph alg;MGraph *mg;alg=create_AdjListGraph();Palg(alg);mg=ALG_MG(alg);printf("转化为邻接矩阵为:\n");Pmg(mg);return 0;}实验十二#include<stdio.h>#include<string.h>#define MAX 50typedef struct{ //学生信息结构char name[20];char id[10];int age;char address[20];char tel[15];}PersonInfo;typedef struct{ //班级信息结构PersonInfo person[MAX];char classid[10];int count;}ClassInfo;int xCinfo(ClassInfo Cinfo[]){ //寻找班级号对应的下标char cid[10];printf("请输入班级号:");scanf("%s",cid);strcpy(Cinfo[0].classid,cid);for(int i=1;Cinfo[i].count>0;i++);i--;for(;i>0;i--){if(strcmp(Cinfo[i].classid,cid)==0)break;}if(i==0){printf("不存在该班级\n");return -1;}elsereturn i;}void inSinfo(ClassInfo Cinfo[]){PersonInfo si;int i;i=xCinfo(Cinfo);if(i==-1)return;printf("请输入学生姓名:");scanf("%s",);printf("请输入学生学号:");scanf("%s",si.id);printf("请输入学生年龄:");scanf("%d",&si.age);printf("请输入学生宿舍号:");scanf("%s",si.address);printf("请输入学生电话:");scanf("%s",si.tel);for(int j=1;Cinfo[i].person[j].age>0;j++);Cinfo[i].person[j]=si;Cinfo[i].person[j+1].age=-1;Cinfo[i].count++;printf("信息已插入\n");}void CreateClass(ClassInfo Cinfo[]){ //建立班级ClassInfo ci;printf("请输入班号:");scanf("%s",ci.classid);printf("请输入班级成员总数:");scanf("%d",&ci.count);for(int i=1;Cinfo[i].count>0;i++);Cinfo[i]=ci;for(int j=1;j<=Cinfo[i].count;j++){ //输入学生信息printf("请输入学生姓名:");scanf("%s",Cinfo[i].person[j].name);printf("请输入学生学号:");scanf("%s",Cinfo[i].person[j].id);printf("请输入学生年龄:");scanf("%d",&Cinfo[i].person[j].age);printf("请输入学生宿舍号:");scanf("%s",Cinfo[i].person[j].address);printf("请输入学生电话:");scanf("%s",Cinfo[i].person[j].tel);printf("\n");}Cinfo[i+1].count=-1;}int xSinfo(ClassInfo Cinfo[],int i){//寻找学号对应的下标char sid[10];printf("请输入学生的学号:");scanf("%s",sid);int j;for(j=Cinfo[i].count;j>0;j--){if(strcmp(Cinfo[i].person[j].id,sid)==0)break;}if(j==0){printf("不存在该学号的学生");return -1;}elsereturn j;}void OutSinfo(ClassInfo Cinfo[]){ //输入学生的信息int i;i=xCinfo(Cinfo);if(i==-1)return;int j;j=xSinfo(Cinfo,i);if(j==-1)return;else{printf("该学生的信息:\n");printf("学号:%s\n",Cinfo[i].person[j].id);printf("姓名:%s\n",Cinfo[i].person[j].name);printf("年龄:%d\n",&Cinfo[i].person[j].age);printf("宿舍:%s\n",Cinfo[i].person[j].address);printf("电话:%s\n",Cinfo[i].person[j].tel);}}void OutCinfo(ClassInfo Cinfo[]){//输入班级信息int i;i=xCinfo(Cinfo);if(i==-1)return;else{printf("班级号:%s\n",Cinfo[i].classid);printf("成员总数:%d\n",Cinfo[i].count);printf("学生信息:\n");for(int j=1;j<=Cinfo[i].count;j++){ //输入班级中学生的信息printf("学号:%s\n",Cinfo[i].person[j].id);printf("姓名:%s\n",Cinfo[i].person[j].name);printf("年龄:%d\n",&Cinfo[i].person[j].age);printf("宿舍:%s\n",Cinfo[i].person[j].address);printf("电话:%s\n",Cinfo[i].person[j].tel);printf("\n");}}}void DelCinfo(ClassInfo Cinfo[]){ //删除班级信息int i;i=xCinfo(Cinfo);if(i==-1)return;else{for(;Cinfo[i].count>0;i++){Cinfo[i]=Cinfo[i+1];}printf("信息已删除\n");}}void DelSinfo(ClassInfo Cinfo[]){ //删除学生信息int i,j;i=xCinfo(Cinfo);if(i==-1){return;}else{j=xSinfo(Cinfo,i);if(j==-1)return;else{for(;j<=Cinfo[i].count;j++){Cinfo[i].person[j]=Cinfo[i].person[j+1];}Cinfo[i].count--;printf("信息已删除\n");}}}void UpdataCinfo(ClassInfo Cinfo[]){ //修改班级信息int i;i=xCinfo(Cinfo);if(i==-1)return;printf("请输入修改后的班号:");scanf("%s",Cinfo[i].classid);printf("信息已修改\n");}void UpdataSinfo(ClassInfo Cinfo[]){ //修改学生信息int i,j;i=xCinfo(Cinfo);if(i==-1){return;}j=xSinfo(Cinfo,i);if(j==-1){return;}printf("请输入学生姓名:");scanf("%s",Cinfo[i].person[j].name);printf("请输入学生学号:");scanf("%s",Cinfo[i].person[j].id);printf("请输入学生年龄:");scanf("%d",&Cinfo[i].person[j].age);printf("请输入学生宿舍号:");scanf("%s",Cinfo[i].person[j].address);printf("请输入学生电话:");scanf("%s",Cinfo[i].person[j].tel);printf("信息已修改\n");}void Infile(ClassInfo Cinfo[]){ //把信息写入文件FILE *fp;int i=1;if((fp=fopen("Cinfo1.txt","wb"))==NULL){printf("打开文件失败\n");return;}for(;Cinfo[i].count>0;i++){if(fwrite(&Cinfo[i],sizeof(ClassInfo),1,fp)!=1)printf("文件写入失败\n");}fclose(fp);}void Outfile(ClassInfo Cinfo[]){ //把文件中的信息写入到程序FILE *fp;int i=1;if((fp=fopen("Cinfo1.txt","rb"))==NULL){printf("打开文件失败\n");return;}for(;!feof(fp);i++){fread(&Cinfo[i],sizeof(ClassInfo),1,fp);}fclose(fp);}int main(void){int choice;ClassInfo Cinfo[MAX];printf("--------------------菜单----------------------\n");printf("1,建立班级 2,插入学生信息3,显示班级信息\n");printf("4,显示学生信息5,删除班级6,删除学生信息\n");printf("7,修改班级信息 8,修改学生信息9,写入文件\n");printf("10,载入文件0,退出\n");do{printf("\n请输入选择:"); //分别调用不同的函数实现不同的功能scanf("%d",&choice);switch(choice){case 1:CreateClass(Cinfo);break;case 2:inSinfo(Cinfo);break;case 3:OutCinfo(Cinfo);break;case 4:OutSinfo(Cinfo);break;case 5:DelCinfo(Cinfo);break;case 6:DelSinfo(Cinfo);break;case 7:UpdataCinfo(Cinfo);break;case 8:UpdataSinfo(Cinfo);break;case 9:Infile(Cinfo);printf("保存文件成功\n");break;case 10:Outfile(Cinfo);printf("载入成功\n");break;case 0:break;}}while(choice!=0);return 0;}。

北邮数据结构实验一线性表及源代码

北邮数据结构实验一线性表及源代码

数据结构实验报告实验名称:实验一——线性表学生姓名:SECRET班级:SECRET班内序号:SECRET学号:SECRET日期:2050年5月20日1.实验要求根据线性表的抽象数据类型的定义,选择下面任一种链式结构实现线性表,并完成线性表的基本功能。

线性表存储结构(五选一):1、带头结点的单链表2、不带头结点的单链表3、循环链表4、双链表5、静态链表线性表的基本功能:1、构造:使用头插法、尾插法两种方法2、插入:要求建立的链表按照关键字从小到大有序3、删除4、查找5、获取链表长度6、销毁7、其他:可自行定义编写测试main()函数测试线性表的正确性。

2. 程序分析2.1 存储结构2.2 关键算法分析关键算法1:头插法自然语言描述:a:在堆中建立新结点b:将a[i]写入到新结点的数据域c:修改新结点的指针域d:修改头结点的指针域。

将新结点加入链表中伪代码描述a:Node <T> * s=new Node <T>b:s->data=a[i]c:s->next=front->next;d:front->next=s2:尾插法自然语言描述:a:在堆中建立新结点:b:将a[i]写入到新结点的数据域:c:将新结点加入到链表中d:修改修改尾指针伪代码描述a:Node <T> * s=new Node <T>b:s->data=a[i]c:r->next=s;d:r=s3:析构/删除函数自然语言描述:a:新建立一个指针,指向头结点b:判断要释放的结点是否存在,c:暂时保存要释放的结点d:移动a 中建立的指针e:释放要释放的指针伪代码描述a:Node <T> * p=frontb:while(p)c: front=pd:p=p->nexte:delete front4:按位查找函数自然语言描述:a:初始化工作指针p 和计数器j,p 指向第一个结点,j=1b:循环以下操作,直到p 为空或者j 等于1b1:p 指向下一个结点b2:j 加1c:若p 为空,说明第i 个元素不存在,抛出异常d:否则,说明p 指向的元素就是所查找的元素,返回元素地址伪代码描述a:Node <T> * p=front->next;j=1;b:while(p&&j!=1)b1:p=p->nextb2:j++c:if(!p) throw ”error”d:return p5:按位查找函数自然语言描述:a:初始化工作指针p 和计数器j,p 指向第一个结点,j=1b:循环以下操作,找到这个元素或者p 指向最后一个结点b1:判断p 指向的结点是不是要查找的值,如果是,返回j,否则p 指向下一个结点,并且j 的值加一c:如果找到最后一个结点还没有找到要查找的元素,返回查找失败信息伪代码描述a:Node <T> * p=front->next;j=1;b:while(p)b1:if(p->next==x) return jp=p->nextj++c:return “error”6:插入函数自然语言描述:a:在堆中建立新结点b:将要插入的结点的数据写入到新结点的数据域c:修改新结点的指针域d:修改前一个指针的指针域,使其指向新插入的结点的位置伪代码描述a:Node <T> * s=new Node <T>;b:s-data=p->datac:s->next=p->nextd:p->next=se:p->data=x7:删除函数自然语言描述:a:从第一个结点开始,查找要删除的位数i 前一个位置i-1 的结点b:设q 指向第i 个元素c:将q 元素从链表中删除d:保存q 元素的数据e:释放q 元素伪代码描述a:q=p->nextb:p->next=q->nextc:x=q->datad:delete q8:遍历打印函数自然语言描述:a:判断该链表是否为空链表,如果是,报错b:如果不是空链表,新建立一个temp 指针c:将temp 指针指向头结点d:打印temp 指针的data 域e:逐个往后移动temp 指针,直到temp 指针的指向的指针的next 域为空伪代码描述If front->next==NULLThrow ”an empty list ”Node<T>* temp=front->next;while(temp->next){cout<<temp->data<<" ";temp=temp->next;}9:获取链表长度函数自然语言描述:a:判断该链表是否为空链表,如果是,输出长度0b:如果不是空链表,新建立一个temp 指针,初始化整形数n 为0c:将temp 指针指向头结点d:判断temp 指针指向的结点的next 域是否为空,如果不是,n 加一,否则return ne: 使temp 指针逐个后移,重复d 操作,直到temp 指针指向的结点的next 域为0,返回n伪代码描述int n=0if front->next==NULLn=0else{Node<T>* temp=front->next;while(temp->next)n++;temp=temp->next;}return n;二代码详细分析1:头插法插入链表四句关键代码Node <T> *s =new Node <T>;s->data=a[i];s->next=front->next;front->next=s;return n;示意图2:尾插法插入链表四句关键代码Node<T> *s=new Node <T>; s->data=a[i];r->next=s;r=s;示意图3:查找算法四句关键代码Node<T>*p=front->next;int j=1;while(p&&j!=i){p=p->next;j++;}示意图4:删除算法关键代码Node<T>*p=front;if(i!=1)p=Get(i-1);Node<T>*q=p->next;p->next=q->next;T x=q->data;delete q;示意图关键算法的时间、空间复杂度头插法/尾插法O(n)按位查找/按值查找O(n)插入操作O(n)3. 程序运行结果流程图4. 总结1、调试时出现的问题及解决的方法在编写按值查找函数时,由于没有处理好指针类型的原因,导致指针无法正常返回,屡屡报错。

数据结构实验代码

数据结构实验代码

单链表的操作#include "myhead.h"#include <iostream.h>typedef struct LNode {ElemType data; // 数据域struct LNode *next; // 后继指针} LNode, *LinkList;Status GetElem_L(LinkList &L, int i, ElemType &e) {// L为带头结点的单链表的头指针,e为返回值、int j;struct LNode *p;p = L->next; j=1; // p指向第一个结点while (p && j<i+1) {p = p->next; j++;} // 顺链后移,j计数if (!p || j>i+1) return ERROR; // 第i元素不存在e = p->data; // 取第i元素值return OK;} // GetElem_LStatus ListInsert_L(LinkList &L, int i, ElemType e) {// 在带头结点的单链表L中第i个位置之前插入元素e, 1≤i≤n+1struct LNode *p , *s; int j = 0;p = L;while (p && j<i-1) {p = p->next; j++;} // 寻找i-1结点if (!p || j>i-1) return ERROR;s = (LinkList) malloc(sizeof(LNode)); // 生成新结点s->data = e;s->next = p->next;p->next = s; // 插入L中return OK;} // ListInsert_Lvoid Listshow(LinkList &L){struct LNode *p; p=L->next;while(p){cout<<p->data<<" ";p=p->next;}cout<<endl;}void create(LinkList &L,int n,int a[])// 逆序输入n 个数据元素,建立带头结点的单链表{cout<<"请输入单链表的"<< n <<"个元素:"<<endl;int i;struct LNode *p;L = (LinkList) malloc (sizeof (LNode));L->next = NULL; // 先建立一个带头结点的单链表for (i = n; i > 0; --i) {p = (LinkList) malloc (sizeof (LNode));cin>>p->data; // 输入元素值p->next = L->next; L->next = p; // 插入}cout<< endl;}Status ListDelete_L(LinkList &L, int i, ElemType &e) {// 在带头结点的单链表L中,删除第i个位置的元素, 1≤i≤n struct LNode *p,*q; int j;p = L; j = 0;while (p->next && j<i-1) {p = p->next; j++;} // 寻找i-1结点if (!p->next || j>i-1) return ERROR;q = p->next; p->next = q->next; // 删除i结点e = q->data; free(q); // 取值并释放结点return OK;} // ListDelete_Lvoid Listdestroy(LinkList &L) //销毁L,保留头结点{// 将单链表重新置为一个空表struct LNode *p;while (L->next) {p=L->next; L->next=p->next;free(p);}}void mergelist(LinkList &la,LinkList &lb,LinkList &lc)//将有序链表la和lb合并为lc,lc的头结点借用原来la的头结点,lb的头结点销毁{struct LNode *pa,*pb,*pc;pa=la->next; pb=lb->next; lc=pc=la;while (pa&&pb) {if(pa->data<=pb->data) {pc=pa;pa=pa->next; }else {pc->next=pb;pc=pb;pb=pb->next;}}pc->next=pa?pa:pb;free(lb);}void main(){LinkList mylist,listb,listc;ElemType e;int a[]={1,12,23,34,45,56,67,78,89,90};int b[]={-6,6,16,26,36,46,96};create(mylist,10,a);create(listb,7,b);GetElem_L(mylist,5,e);cout<<"单链表的第5个元素是:"<<e<<endl;cout<<"单链表的所有元素是:";Listshow(mylist);ListInsert_L(mylist,7,60);cout<<"插入第7个元素后单链表中的所有元素是:";Listshow(mylist);ListDelete_L(mylist,5,e);cout<<"删除了第五个元素后的单链表中的所有元素是:";Listshow(mylist);cout<<"删除的第五个元素是:";cout<<e<<endl;cout<<"listb中的元素有:";Listshow(listb);mergelist(mylist,listb,listc);cout<<"合并之后listc中的元素有:";Listshow(listc);Listdestroy(mylist);cout<<"销毁后单链表的元素是:";Listshow(mylist);}串实验1.采用定长顺序显示表示串长的结构来存储串(结构定义见课件第15张幻灯片)2.实现BF算法(即朴素算法),BF函数头如下:(参见课件第21张幻灯片)int Index_BF(SString S, SString T) {}// 返回子串T在主串S中第0个字符之后的位置。

数据结构实验与实训教程源代码

数据结构实验与实训教程源代码

i
第一部分 预备知识
预备知识
例 1.1 #include <stdio.h> int sumabc(int a, int b, int c) /* 求三个整数之和*/ { int s; a=b+c; s=a+b+c; return s; } void displayLine(void) { printf(”----------------------\n“); } void main( ) { int x,y, z ,sabc; x=y=z=8; display(); /* 画一条线 */ printf(“\n sum=%d”,sumabc(x,y,z)); /* 在输出语句中直接调用函数 sumabc( ) */ printf(“\n %6d%6d%6d”,x,y,z); display();/* 画一条线 */ x=2; y=4; z=6; sabc =sumabc(x, y, z); /* 在赋值语句中调用函数 sumabc( ) */ printf(“\n “ sum=%d”, sabc); printf(“\n %6d%6d%6d”,x,y,z); display();/* 画一条线 */ } 例 1.2 int sumabc(int *a, int b, int c) { int s; *a=b+c; s=*a+b+c;
2
}//while(1) }//main
3
第二部分 基础实验
实验 1 线性表的基本操作
四、参考程序
程序 1:题 1 线性表基本操作函数 #include<stdio.h> #include<stdlib.h> #include<alloc.h> struct LinearList /*定义线性表结构*/ { int *list; /* 存线性表元素 */ int size; /* 存线性表长度 */ int MaxSize; /* 存 list 数组元素个数 */ }; typedef struct LinearList LIST; void InitList( LIST *L, int ms ) /* 初始化线性表 */ { if( (L->list = 1 ) == NULL ) { printf( "内存申请错误!\n" ); exit( 1 ); } 2 L->MaxSize = ms; } int InsertList( LIST *L, int /* item:记录值 rc:插入位置 { int i; if( 3 ) return -1; if( rc < 0 ) item, int rc ) */备知识实验

数据结构实验源代码

数据结构实验源代码

数据结构实验源代码【附】数据结构实验源代码范本一、实验背景与目的1.1 实验背景在计算机科学中,数据结构是指数据元素之间的关系,以及为操作这些数据元素所提供的方法。

数据结构对于程序的设计和性能优化具有重要影响。

1.2 实验目的本实验旨在通过编写和实现不同的数据结构,加深学生对数据结构的理解,掌握基本的数据结构操作方法。

二、实验内容2.1 线性表2.1.1 顺序表2.1.1.1 初始化顺序表2.1.1.2 插入元素到顺序表2.1.1.3 删除顺序表中的元素2.1.1.4 遍历顺序表2.1.1.5 查找指定元素在顺序表中的位置2.1.2 链表2.1.2.1 初始化链表2.1.2.2 插入元素到链表2.1.2.3 删除链表中的元素2.1.2.4 遍历链表2.1.2.5 查找指定元素在链表中的位置2.2 栈2.2.1 初始化栈2.2.2 进栈操作2.2.3 出栈操作2.2.4 获取栈顶元素2.2.5 判断栈是否为空2.3 队列2.3.1 初始化队列2.3.2 入队操作2.3.3 出队操作2.3.4 获取队首元素2.3.5 判断队列是否为空三、实验步骤3.1 线性表实现在实现顺序表和链表时,首先需要定义数据结构和所需的操作函数。

然后进行初始化、添加元素、删除元素等操作。

最后进行遍历和查找操作,并检验实验结果是否符合预期。

3.2 栈实现栈的实现过程与线性表类似,需要定义栈的数据结构和所需的函数,然后进行初始化、进栈、出栈等操作。

3.3 队列实现队列的实现也与线性表类似,需要定义队列的数据结构和函数,进行初始化、入队、出队等操作。

四、数据结构实验源代码以下是实验代码的源代码范本,包括线性表、栈和队列的实现。

(代码略,如需获取,请查看附件)五、附件本文档附带的附件为数据结构实验源代码。

六、法律名词及注释6.1 数据结构:计算机科学中,数据结构是指数据元素之间的关系,以及为操作这些数据元素所提供的方法。

6.2 顺序表:一种物理上相邻的存储结构,元素按照顺序依次存放。

数据结构实验系统源代码(期末作业)

数据结构实验系统源代码(期末作业)

/*树子系统*/#include <stdio.h>#include <malloc.h>#define MAX 100int count=0; /*定义计算结点个数的变量*/typedef struct tnode{char data;struct tnode *lchild,*rchild;}BT;BT *CreateBTree(){BT *t;char ch;scanf("%c",&ch);getchar();if(ch=='0')t=NULL;else{t=(BT *)malloc(sizeof(BT));t->data=ch;printf("请输入%c结点的左孩子结点:",t->data);t->lchild=CreateBTree();printf("请输入%c结点的右孩子结点:",t->data);t->rchild=CreateBTree();}return t;}void ShowBTree(BT *T) /*用广义表表示法显示二叉树*/{ if (T!=NULL) /*当二叉树非空时*/{ printf("%c",T->data); /*输入该结点数据域*/if(T->lchild!=NULL) /*若其左子树非空*/{ printf("("); /*输入左括号*/ShowBTree(T->lchild); /*递归调用该函数输出其左子树各结点*/if(T->rchild!=NULL) /*若其右子树非空*/{ printf(","); /*输出逗号*/ShowBTree(T->rchild); /*递归调用该函数输出其右子树各结点*/ }printf(")");}elseif(T->rchild!=NULL) /*二叉树左子树为空,右子树不为空时*/{printf("("); /*输入左括号*/ShowBTree(T->lchild); /*递归调用该函数输出其左子树各结点*/if(T->rchild!=NULL) /*若其右子树非空*/{ printf(","); /*输出逗号*/ShowBTree(T->rchild); /*递归调用该函数输出其右子树各结点*/ }printf(")");}}}void PreOrder(BT *T) /* 先序遍历二叉树T*/{ if(T==NULL) return; /* 递归调用的结束条件*/ else{ printf("%c",T->data); /* 输出结点的数据域*/PreOrder(T->lchild); /* 先序递归遍历左子树*/PreOrder(T->rchild); /* 先序递归遍历右子树*/ }}void InOrder(BT *T) /* 中序遍历二叉树T*/{ if(T==NULL) return; /* 递归调用的结束条件*/else{ InOrder(T->lchild); /* 中序递归遍历左子树*/ printf("%c",T->data); /* 输出结点的数据域*/InOrder(T->rchild); /* 中序递归遍历右子树*/}}void PostOrder(BT *T) /* 后序遍历二叉树T*/{ if (T==NULL) return; /* 递归调用的结束条件*/else{ PostOrder(T->lchild); /* 后序递归遍历左子树*/PostOrder(T->rchild); /* 后序递归遍历右子树*/printf("%c",T->data); /* 输出结点的数据域*/}}void LevelOrder(BT *T) /*按层次遍历二叉树T*/{ int f,r; /*定义队头队尾指针*/BT *p,*q[MAX]; /*定义循环队列,存放结点指针*/ p=T;if(p!=NULL) /*若二叉树非空,则根结点地址入队*/ { f=1; q[f]=p; r=2; }while(f!=r) /*队列不空时*/{ p=q[f];printf("%c",p->data); /*访问队首结点的数据域*/if(p->lchild!=NULL) /*将队首结点的左孩子入队*/{ q[r]=p->lchild; r=(r+1)%MAX; }if(p->rchild!=NULL) /*将队首结点的右孩子入队*/{ q[r]=p->rchild; r=(r+1)%MAX; }f=(f+1)%MAX;}}void Leafnum(BT *T) /*求二叉树叶子结点数*/{ if(T) /*若树不为空*/{ if(T->lchild==NULL && T->rchild==NULL)count++; /*全局变量count为计数值,其初值为0*/ Leafnum(T->lchild); /*递归统计T的左子树叶子结点数*/Leafnum(T->rchild); /*递归统计T的右子树叶子结点数*/ }}void Nodenum(BT *T){ if(T) /*若树不为空*/{count++; /*全局变量count为计数值,其初值为0*/Nodenum(T->lchild); /*递归统计T的左子树结点数*/Nodenum(T->rchild); /*递归统计T的右子树结点数*/ }}int TreeDepth(BT *T) /*求二叉树深度*/{ int ldep=0,rdep=0; /*定义两个整型变量,用以存放左、右子树的深度*/if(T==NULL)return 0;else{ ldep=TreeDepth(T->lchild); /*递归统计T的左子树深度*/rdep=TreeDepth(T->rchild); /*递归统计T的右子树深度*/if(ldep>rdep)return ldep+1;elsereturn rdep+1;}}void MenuTree() /*显示菜单子函数*/{printf("\n 二叉树子系统");printf("\n =================================================");printf("\n| 1——建立一个新二叉树|");printf("\n| 2——广义表表示法显示|");printf("\n| 3——先序遍历|");printf("\n| 4——中序遍历|");printf("\n| 5——后序遍历|");printf("\n| 6——层次遍历|");printf("\n| 7——求叶子结点数目|");printf("\n| 8——求二叉树总结点数目|");printf("\n| 9——求树深度|");printf("\n| 0——返回|");printf("\n ================================================");printf("\n请输入菜单号(0-9):");}btree(){BT *T=NULL;char ch1,ch2,a;ch1='y';while(ch1=='y'||ch1=='Y'){ MenuTree();scanf("%c",&ch2);getchar();switch(ch2){case '1':printf("请按先序序列输入二叉树的结点:\n");printf("说明:输入结点后按回车('0'表示后继结点为空):\n");printf("请输入根结点:");T=CreateBTree();printf("二叉树成功建立!");break;case '2':printf("二叉树广义表表示法如下:");ShowBTree(T);break;case '3':printf("二叉树的先序遍历序列为:");PreOrder(T);break;case '4':printf("二叉树的中序遍历序列为:");InOrder(T);break;case '5':printf("二叉树的后序遍历序列为:");PostOrder(T);break;case '6':printf("二叉树的层次遍历序列为:");LevelOrder(T);break;case '7':count=0;Leafnum(T);printf("该二叉树有%d个叶子。

数据结构实验一(完整版)

数据结构实验一(完整版)

数据结构实验一:线性表实验报告#include <string.h>#include <ctype.h>#include <malloc.h> // malloc()等#include <limits.h> // INT_MAX等#include <stdio.h> // EOF(=^Z或F6),NULL#include <stdlib.h> // atoi()#include <io.h> // eof()#include <math.h> // floor(),ceil(),abs()#include <process.h> // exi t()#include <iostream.h> // cout,cin// 函数结果状态代码#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0#define INFEASIBLE -1// #define OVERFLOW -2 因为在math.h中已定义OVERFLOW的值为3,故去掉此行typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等typedef int Boolean; // Boolean是布尔类型,其值是TRUE或FALSEtypedef int ElemType;#define LIST_INIT_SIZE 10 // 线性表存储空间的初始分配量#define LISTINCREMENT 2 // 线性表存储空间的分配增量struct SqListElemType *elem; // 存储空间基址int length; // 当前长度int listsize; // 当前分配的存储容量(以sizeof(ElemType)为单位)};/**********************************************************/ /* 顺序表示的线性表的基本操作(12个) *//**********************************************************/ Status InitList(SqList &L){ // 操作结果:构造一个空的顺序线性表---------------1L.elem=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));if(!L.elem)exit(OVERFLOW); // 存储分配失败L.length=0; // 空表长度为0L.listsize=LIST_INIT_SIZE; // 初始存储容量return OK;}Status DestroyList(SqList &L){ // 初始条件:顺序线性表L已存在。

数据结构 图实验 实验代码

数据结构  图实验  实验代码

1.邻接矩阵作为存储结构:#include <stdio.h>#include <stdlib.h>#define MaxVertexNum 100typedef struct{char verxs[MaxVertexNum];int edges[MaxV ertexNum][MaxVertexNum];int n,e;}MGraph;void creatMGraph(MGraph *G){int i,j,k;char a;printf("Input VertexNum(n)andEdgesNum(e):");scanf("%d,%d",&G->n,&G->e);scanf("%c",&a);printf("Input Vertex string");for(i=0;i<G->n;i++){scanf("%c",&a);G->verxs[i]=a;}for(i=0;i<G->n;i++)for(j=0;j<G->n;j++)G->edges[i][j]=0;printf("Input edges,Creat Adjacency Matrix\n");for(k=0;k<G->e;k++){scanf("%d%d",&i,&j);G->edges[i][j]=1;G->edges[j][i]=1;}}typedef enum{FALSE,TRUE}Boolean;Boolean visited[MaxVertexNum];void DFSM(MGraph*G,int i){int j;printf("%c",G->verxs[i]);visited[i]=TRUE;for(j=0;j<G->n;j++)if(G->edges[i][j]==1&&!visited[j])DFSM(G,j);}void DFS(MGraph*G){int i;for(i=0;i<G->n;i++)visited[i]=FALSE;for(i=0;i<G->n;i++)if(!visited[i])DFSM(G,i);}void BFS(MGraph*G,int k){int i,j,f=0,r=0;int cq[MaxVertexNum];for(i=0;i<G->n;i++)visited[i]=FALSE;for(i=0;i<G->n;i++)cq[i]=-1;printf("%c",G->verxs[k]);visited[k]=TRUE;cq[r]=k;while(cq[f]!=-1){ i=cq[f];f=f+1;for(j=0;j<G->n;j++)if(G->edges[i][j]==1&&!visited[j]){printf("%c",G->verxs[j]);visited[j]=TRUE;r=r+1;cq[r]=j;}}}void main(){int i;MGraph*G;G=(MGraph*)malloc(sizeof(MGraph));creatMGraph(G);printf("Print Graph DFS:");DFS(G);printf("\n");printf("Print Graph BFS:");BFS(G,3);printf("\n");}2.邻接链表作为存储结构:#include"stdio.h"#include"stdlib.h"#define MaxVertexNum 50 /*定义最大顶点数*/typedef struct node{ /*边表结点*/int adjvex; /*邻接点域*/struct node *next; /*链域*/}EdgeNode;typedef struct vnode{ /*顶点表结点*/char vertex; /*顶点域*/EdgeNode *firstedge; /*边表头指针*/}VertexNode;typedef VertexNode AdjList[MaxVertexNum]; /*AdjList是邻接表类型*/ typedef struct {AdjList adjlist; /*邻接表*/int n,e; /*图中当前顶点数和边数*/} ALGraph; /*图类型*//* 建立图的邻接表*/void CreatALGraph(ALGraph *G){int i,j,k;char a;EdgeNode *s; /*定义边表结点*/printf("Input VertexNum(n)andEdgesNum(e): ");scanf("%d,%d",&G->n,&G->e); /*读入顶点数和边数*/scanf("%c",&a);printf("Input Vertex string:");for(i=0;i<G->n;i++) /*建立边表*/{scanf("%c",&a);G->adjlist[i].vertex=a; /*读入顶点信息*/G->adjlist[i].firstedge=NULL; /*边表置为空表*/}printf("Input edges,Creat Adjacency Matrix\n");for(k=0;k<G->e;k++) { /*建立边表*/scanf("%d%d",&i,&j); /*读入边(Vi,Vj)的顶点对序号*/s=(EdgeNode *)malloc(sizeof(EdgeNode)); /*/生成边表结点*/s->adjvex=j; /*邻接点序号为j*/s->next=G->adjlist[i].firstedge;G->adjlist[i].firstedge=s; /*将新结点*S插入顶点Vi的边表头部*/s=(EdgeNode *)malloc(sizeof(EdgeNode));s->adjvex=i; /*邻接点序号为i*/s->next=G->adjlist[j].firstedge;G->adjlist[j].firstedge=s; /*将新结点*S插入顶点Vj的边表头部*/}}/* 定义标志向量,为全局变量*/typedef enum{FALSE,TRUE} Boolean;Boolean visited[MaxVertexNum];/* DFS:深度优先遍历的递归算法*/void DFSM(ALGraph *G,int i){ /*以Vi为出发点对邻接链表表示的图G进行DFS搜索*/ EdgeNode *p;printf("%c ",G->adjlist[i].vertex); /*访问顶点Vi*/visited[i]=TRUE; /*标记Vi已访问*/p=G->adjlist[i].firstedge; /*取Vi边表的头指针*/while(p) { /*依次搜索Vi的邻接点Vj,这里j=p->adjvex*/if(! visited[p->adjvex]) /*若Vj尚未被访问*/DFSM(G,p->adjvex); /*则以Vj为出发点向纵深搜索*/ p=p->next; /*找Vi的下一个邻接点*/}}void DFS(ALGraph *G){int i;for(i=0;i<G->n;i++)visited[i]=FALSE; /*标志向量初始化*/for(i=0;i<G->n;i++)if(!visited[i]) /*Vi未访问过*/DFSM(G,i); /*以Vi为源点开始DFS搜索*/}/* BFS:广度优先遍历*/void BFS(ALGraph *G,int k){ /*以Vk为源点对用邻接链表表示的图G进行广度优先搜索*/int i,f=0,r=0;EdgeNode *p;int cq[MaxVertexNum]; /*定义FIFO队列*/for(i=0;i<G->n;i++)visited[i]=FALSE; /*标志向量初始化*/for(i=0;i<=G->n;i++)cq[i]=-1; /*初始化标志向量*/printf("%c ",G->adjlist[k].vertex); /*访问源点Vk*/visited[k]=TRUE;cq[r]=k; /*Vk已访问,将其入队。

数据库与数据结构实验(含源代码)

数据库与数据结构实验(含源代码)

实验一 一元稀疏多项式的表示及加法运算一、需求分析1.程序的功能:(1) 两个多项式以指数递增的顺序输入;(选做内容部分,多项式也可未按指数递增的顺序输入。

)(2) 设计的数据结构应有利于表示任意一元稀释多项式;(3) 输出原始多项式及两个多项式相加后的运算结果。

2.输入输出的要求:分别输入一元多项式各项的系数和指数,系数以浮点数输入,指数以整型数输入。

输出为具体各个一元多项式的形式,如7+3*x+9*x^8+5*x^17。

3.测试数据:(1) 8177+395x x x ++,788229x x x +-(2) 0,788229x x x +-(3) 10788229x x x +-,1-二、 概要设计1.本程序所用的数据结构的定义:本程序中主要用了单链表的线性结构,其数据结构的定义如下: struct link{float ceof; //每项系数int exp; //每项指数link *next; //指针域};并构造了一个多项式类:class Polynomial ;类定义如下:class Polynomial //多项式类定义{link *head; //头指针public:void creat(); //输入每项系数和指数创建多项式 void paixu(); //多项式按指数从小到大排序 void shuchu(); //输出多项式void addtwo(link*ha,link*hb); //将两个多项式相连构成一个新的多项式,再通过排序和除去系数为0项//实现两个多项式相加 void qingling(); //将多项式中系数为0的项消去 link *gethead(); //取多项式的头结点 };2.主程序的流程及各程序模块之间的层次关系:主程序的具体代码如下:#include"Polynomail.h"using namespace std;void main(){Polynomial A,B,C;cout<<"请输入多项式A:"<<endl;A.creat ();A.qingling ();A.paixu ();cout<<"请输入多项式B:"<<endl;B.creat ();B.qingling ();B.paixu ();cout<<"多项式A为:"<<endl;A.shuchu ();cout<<"多项式B为:"<<endl;B.shuchu ();cout<<"A和B相加为:"<<endl;C.addtwo (A.gethead (),B.gethead ());C.paixu ();C.qingling ();C.shuchu ();}3.主程序流程如下:三、详细设计各模块算法如下:1.创建多项式void Polynomial::creat () //输入每项系数和指数创建多项式{link *p,*q,*s;cout<<"请依次输入每项系数和指数,以空格分开,指数<0,输入完成!"<<endl;float c;int e;cin>>c>>e; //输入系数和指数p=q=new link;p->next =NULL;while(e>=0){s=new link;s->ceof =c;s->exp =e;q->next =s;q=s;cin>>c>>e;}q->next =NULL;head=p;}2.多项式每项按指数由小到大排序void Polynomial::paixu () //多项式按指数从小到大排序{link *p,*q;float a;int b;p=head->next;while(p!=NULL){q=p->next ;while(q!=NULL){if(p->exp >q->exp ) //后面的某一项指数小于前面的某一项,将两//项系数和指数值交换{a=p->ceof ;b=p->exp ;p->ceof =q->ceof ;p->exp =q->exp ;q->ceof =a;q->exp =b;q=q->next ;}elseif(p->exp ==q->exp ) //两项指数相等,则系数相加,后面一项系数//置为0{p->ceof =p->ceof +q->ceof ;q->ceof =0;q=q->next ;}else q=q->next ;}p=p->next ;}}3.将多项式中系数为0的项消去void Polynomial::qingling ()//将多项式中系数为0的项消去{link *p,*q;p=head ;q=head->next ;while(q!=NULL){if(q->ceof ==0){p->next =q->next ;delete q;q=p->next ;}else{p=p->next ;q=p->next ;}}}4.输出多项式void Polynomial::shuchu ()//输出多项式{link *p;p=head->next ;if(p==NULL)cout<<"0";else{while(p->next !=NULL){if(p->exp ==0){cout<<p->ceof ;}elseif(p->exp ==1){cout<<p->ceof <<"X";}else{cout<<p->ceof <<"X^"<<p->exp ;}p=p->next ;if(p->ceof >0)cout<<"+";}if(p->exp ==0) // 输出最后一项{cout<<p->ceof ;}elseif(p->exp ==1)cout<<p->ceof <<"X";elsecout<<p->ceof <<"X^"<<p->exp ;}cout<<endl;}5.将两个多项式相连构成一个新的多项式,再通过排序和除去系数为0项,实现两个多项式相加void Polynomial::addtwo (link *ha,link *hb)//将两个多项式相连构成一个新的多项式,再通过排序和除去系数为0项,实现两个多项式相加{link *a,*b,*c;link *p;a=ha->next ;p=b=new link;while(a!=NULL) //将A复制进C{c=new link;c->ceof =a->ceof ;c->exp =a->exp ;c->next =NULL;b ->next=c;b=b->next ;a=a->next ;}a=hb->next ;while(a!=NULL) //将B复制进C,接在A后面{c=new link;c->ceof =a->ceof ;c->exp =a->exp ;c->next =NULL;b ->next=c;b=b->next ;a=a->next ;}b =NULL;head=p;}四、 调试分析1.调试中遇到的问题及对问题的解决方法:在调试中,将A 、B 两个多项式输入输出都没有问题,但是当将A 、B 相加时,运行出错,程序必须终止。

实验报告数据结构课程设计源代码

实验报告数据结构课程设计源代码

表达式类型的实现——实习报告一.需求分析1. 编写一个程序,通过前缀表达式来构造一个与之对应的算术表达式并存入二叉树中,通过中序遍历二叉树输出表达式及对其进行变量赋值,通过后序遍历二叉树计算表达式的值。

2. 本程序功能有:存储表达式、对表达式进行赋值计算、求偏导、计算三角函数、合并常数及接受原书写形式的表达式。

3. 测试数据(1). 分别输入0 ; a ; -91 ; +a*bc ; +*5^x2*8x ; +++*3^x3*2^x2x6并输出。

(2). 每输入一个表达式,对其中的变量进行赋值,再对表达式求值。

二.概要设计按照要求,需要以二叉树来存储表达式,但在构造过程中还需要用到栈来实现前缀表达式与二叉树之间的转换。

1. 抽象数据类型栈的定义:ADT SqStack{数据对象:D={ai |ai为整型或字符型}数据关系:R={<ai , ai-1> |ai ,ai-1∈D}基本操作:Status InitStack(SqStack&S);此函数用于创建一个空栈Status StackEmpty(SqStack S);此函数用于判断栈是否为空Status StackFull(SqStack S);此函数用于判断栈是否已满Status Push(SqStack&S, SElemType e);将数据元素e入栈Status Pop(SqStack&S, SElemType&e);出栈,并以e返回出栈的元素Status GetTop(SqStack S, SElemType&e);若栈不空,则以e返回栈顶元素}ADT SqStack2. 二叉树表达式数据类型ATD BiTNode{数据对象:D= { a i | a i∈SqStack}数据关系:R= {<ai , ai-1> |ai ,ai-1∈D}基本操作:Status InputExpr(char*string,int flag);以字符串形式读取输入void JudgeValue(BiTree*E,char*string,int i);判断字符string[i],如果是'0'-'9'常量之间,二叉树结点存为整型;否则,存为字符型 Status ReadExpr(BiTree*E,char*exprstring);以正确的前缀表示式并构造表达式EStatus PriCmp(char c1,char c2);如果两个字符是运算符,比较两个运算符的优先级,c1比c2优先,返回OK,否则返回ERRORvoid WriteExpr(BiTree E);用带括弧的中缀表达式输出表达式void Assign(BiTree*E,char V,int c,int*flag);实现对表达式中的所有变量V的赋值(V=c),参数flag为表示是否赋值过的标志long Operate(int opr1,char opr,int opr2);运算符运算求值,参数opr1,opr2为常量,opr为运算符,根据不同的运算符,实现不同的运算,返回运算结果double Operate1(char opr,double opr1);三角函数运算求值,参数opr为常量,opr1为运算符,根据不同的运算符,实现不同的运算,返回运算结果Status Check(BiTree E);检查表达式是否还存在没有赋值的变量,以便求算数表达式的值long Value(BiTree E);对算术表达式求值void CompoundExpr(char P,BiTree&E1,BiTree E2);构造一个新的复合表达式Status ReadInorderExpr(char*string,char*pre_expr);以表达式的原书写形式输入,表达式的原书写形式字符串string变为字符串pre_expr,后调用reversal_string()函数反转得到前缀表达式pre_exprvoid ReversalString(char*exprstring);将字符串exprstring反转过来void MergeConst(BiTree*E);常数合并操作函数,合并表达式E中所有常数运算int IsOperator(char c);判断是否操作符void Diff(BiTree&E,char v);求偏导数}ADT BiTNode3. 主程序int main() {while(TRUE) {判断用户选择的操作;执行所选操作,并适时提示用户输入及输出运算结果;若用户选择退出,则执行exit(0)退出程序;};4. 程序调用关系:主程序模块三.详细设计1. 数据类型:二叉树数据类型:typedef enum{INT,CHAR}ElemTag;/*INT为整型数据num,CHAR为字符型数据c*/typedef struct TElemType{ElemTag tag;/*{INT,CHAR}指示是整型还是字符型*/int num;/*tag=INT时,为整型*/char c;/*tag=CHAR时,为字符型*/}TElemType;二叉树节点类型:typedef struct BiTNode{TElemType data;/* 二叉树存储的数据*/struct BiTNode*lchild,*rchild; /* 左右孩子指针*/}BiTNode,*BiTree;2. 函数实现:(以伪码表示)Status InputExpr(char *string,int flag) //此函数用于表达式的输入与存储{if(flag==0)cout<<"\n请输入正确的前缀表示式:";else cout<<"\n请以表达式的原书写形式输入正确表示式:";fflush(stdin);/*清理缓冲区*/gets(string);/*从键盘输入一串字符串作为表达式*/if(strlen(string)==1)/*输入的表达式字符串长度为1*/if(string[0]=='+'||string[0]=='-'||string[0]=='*'||string[0]=='/'||string[0]=='^')/*输入的表达式只有一个运算符*/{cout<<"\n表达式只有一个字符,为运算符,错误!";return ERROR;}else if((string[0]>='0'&&string[0]<'9')||(string[0]>='a'&&string[0]<='z')||(string[0]>='A'&&string[0]<='Z')) /*输入的表达式只有一个数字或字符*/{cout<<"\n表达式只有一个字符!";return OK;}else {cout<<"\n输入的字符不是运算符也不是变量常量,错误!";return ERROR;}return OK;}void JudgeValue(BiTree *E,char *string,int i) //此函数用于判断字符string[i],如果是'0'-'9'常量之间,二叉树结点存为整型;否则,存为字符型{if(string[i]>='0'&&string[i]<='9') {(*E)->data.tag=INT;(*E)->data.num=string[i]-'0';}//string[i]为常量else if(string[i]>='10'&&string[i]<='20') {(*E)->data.tag=INT;(*E)->data.num=SaveNumber[string[i]];} //string[i]为常量,存于数组save_number中else {(*E)->data.tag=CHAR;(*E)->data.c=string[i];} /*string[i]为变量,对数据进行变量标记}/*以正确的前缀表示式并构造表达式E*/Status ReadExpr(BiTree *E,char *exprstring){定义栈;为树的根结点分配空间;len=strlen(exprstring);/*len赋值为表达式的长度*/if(len==1) JudgeValue(E,exprstring,0);/*将exprstring[0]存入二叉树的结点中*/else {JudgeValue(E,exprstring,0);/*将exprstring[0]存入二叉树的结点中*/InitStack(S);/*初始化栈*/q=(*E);Push(S,q);/*入栈*/Push(S,q);/*入栈,根结点入栈两次是为判断先序输入的表达式是不是正确的表达式*/for(i=1;i<len&&!StackEmpty(S);i++){p=(BiTree)malloc(sizeof(BiTNode));JudgeValue(&p,exprstring,i);/*将exprstring[i]存入二叉树的结点中*/p->lchild=NULL;p->rchild=NULL;if(exprstring[i]=='+'||exprstring[i]=='-'||exprstring[i]=='*'||exprstring[i]=='/'||exprstring[i]=='^'){/*为运算符,运算符入栈,左孩子不空,向左孩子走,否则,如果右孩子不空,向右孩子走*/if(!q->lchild) {q->lchild=p;Push(S,p);q=p;}else {q->rchild=p;Push(S,p);q=p;}}else /*不是运算符,运算符出栈*/{if(!q->lchild) {q->lchild=p;Pop(S,q);}else {q->rchild=p;Pop(S,q);}}}if(StackEmpty(S)&&i>=len) return OK;/*栈空且i>=len,说明输入的表达式是正确的*/ else /*输入的表达式是错误的*/{cout<<"\n输入的表达式有误!";return ERROR;}}}//此函数用于比较两个运算符的优先级,若c1比c2优先,返回OK,否则返回ERROR Status PriCmp(char c1,char c2){if((c1=='^'||c1=='*'||c1=='-'||c1=='+'||c1=='/')&&(c2=='^'||c2=='*'||c2=='-'||c2=='+'||c2=='/')){/*c1和c2为运算符*/if(c1=='^'){/*c1为指数运算符,则当c2不为'^'时,c1比c2优先*/if(c2!='^') return OK;else return ERROR;}else if(c1=='*'||c1=='/'){/*c1为乘法或除法运算符,则当c2为'+'或'-',c1比c2优先*/if(c2=='^'||c2=='*'||c2=='/') return ERROR;else return OK;}else return ERROR;/*其余,c1不比c2优先*/}else return ERROR;/*c1和c2不是运算符*/}此函数递归实现用带括弧的中缀表达式输出表达式void WriteExpr(BiTree E){if(E)/*树不为空*/{ //先递归左子树if(E->lchild&&E->lchild->data.tag==CHAR)/*E的左孩子不为空,且左孩子为字符*/{if(PriCmp(E->data.c,E->lchild->data.c)){cout<<"(";WriteExpr(E->lchild);cout<<")";}/*带括弧输出左子树*/else WriteExpr(E->lchild);/*否则,不带括弧输出左子树*/}else WriteExpr(E->lchild);/*否则,输出左子树*//*访问输出根结点的值*/if(E->data.tag==INT){cout<<E->data.num;}else cout<<E->data.c;//后递归右子树if(E->rchild&&E->rchild->data.tag==CHAR){//E的右孩子不为空,且右孩子为字符if(PriCmp(E->data.c,E->rchild->data.c)){cout<<"(";WriteExpr(E->rchild);cout<<")";}/*带括弧输出右子树*/else WriteExpr(E->rchild);/*否则,不带括弧输出右子树*/}else WriteExpr(E->rchild);/*否则,输出右子树*/}}此函数递归实现对表达式中的所有变量V的赋值(V=c),参数flag为表示是否赋值过的标志void Assign(BiTree *E,char V,int c,int *flag){if(*E){if((*E)->data.tag==CHAR&&(*E)->data.c==V) {(*E)->data.tag=INT;(*E)->data.num=c;*flag=1;} /*如果找到要赋值的变量,赋值*/Assign(&((*E)->lchild),V,c,flag);/*递归左子树*/Assign(&((*E)->rchild),V,c,flag);/*递归左子树*/}}/*运算符运算求值,参数opr1,opr2为常量,opr为运算符,根据不同的运算符,实现不同的运算,返回运算结果*/long Operate(int opr1,char opr,int opr2){switch(opr){case '+':/*加法*/result=opr1+opr2;return result;break;case '-':/*减法*/result=opr1-opr2;return result;break;case '*':/*乘法*/result=opr1*opr2;return result;break;case '/':/*除法,除法是在整型类型上的除法*/result=opr1/opr2;return result;break;case '^':/*指数运算*/result=pow(opr1,opr2);return result;break;default:break;}}/*三角函数运算求值,参数opr为常量,opr1为运算符,根据不同的运算符,实现不同的运算,返回运算结果*/double Operate1(char opr,double opr1){switch(opr){case 's'://正弦运算result1=sin(opr1);return result1;break;case 'c'://余弦运算result1=cos(opr1);return result1;break;case 't'://正切运算result1=tan(opr1);return result1;break;default:break;}}/*检查表达式是否还存在没有赋值的变量,以便求算数表达式的值*/Status Check(BiTree E){if(E&&E->data.tag==CHAR){/*树不为空*/if(E->data.c!='*'&&E->data.c!='^'&&E->data.c!='-'&&E->data.c!='+'&&E->data.c!='/'){cout<<"\n表达式中仍存在变量没有赋值!没法求出表达式的值!";return ERROR;}/*存在变量,提示信息,后返回ERROR*/if(Check(E->lchild)) Check(E->rchild);}}/*对算术表达式求值*/long Value(BiTree E){if(E){/*树不为空*/if(!E->lchild&&!E->rchild&&E->data.tag==INT) return (E->data.num);/*结点的左孩子和右孩子为空,为叶子结点,返回结点的值*/return Operate(Value(E->lchild),E->data.c,Value(E->rchild));/*运算求值,后根遍历的次序对表达式求值,其中参数递归调用了Value()函数求左子树的值和右子树的值*/}}/*构造一个新的复合表达式*/void CompoundExpr(char P,BiTree &E1,BiTree E2){为结点E申请空间;E->data.tag=CHAR;E->data.c=P;/*申请到的结点值为P*/E->lchild=E1;/*结点的左孩子为E1*/E->rchild=E2;/*结点的右孩子为E2*/E1=E;/*(*E1)为根结点*/cout<<"\n表达式E复合成功!其表达式变为:\n";WriteExpr(E);/*输出复合好的表达式*/}/*此函数以表达式的原书写形式输入,表达式的原书写形式字符串string变为字符串pre_expr*//*后调用reversal_string()函数反转得到前缀表达式pre_expr*/Status ReadInorderExpr(char *string,char *PreExpr){int i,j,len,CharNumber=1;/*len表示字符串string的长度,char_number是记录数组save_number[]的个数*/int number;/*保存大于9的常量*/InitStack1(S);/*初始栈*/Push1(S,'#');/*先将字符'#'入栈,用来表示作为栈的最底一个元素*/len=strlen(string);/*len为字符串string的长度*/c=string[len-1];/*从字符串的最后一个字符开始向前扫描*/i=len-1;while(!StackEmpty1(S)&&i>=0){/*栈不为空且i大于等于0*/if(c=='('){/*字符为'('*/Pop1(S,c);/*出栈,赋值给c*/while(c!=')'){/*假如c不为')',出栈*/*PreExpr++=c;if(!StackEmpty1(S)&&GetTop1(S,c1)&&c1!='#') Pop1(S,c);else {cout<<"\n输入的表达式有误!";return ERROR;}}}else if(c==')'){Push1(S,c);} /*字符为')',入栈*/else if(c>='0'&&c<='9'){/*字符为'0'-'9'之间,循环扫描string前一个字符,后确定常量的大小*/number=c-'0';/*number为第一个常量字符的ASCII码-48*/for(c1=string[i-1],j=1;(c1>='0'&&c1<='9')&&i>=0;j++,i--){/*循环扫描string前一个字符,求出常量后赋给number*/number=(c1-'0')*pow(10,j)+number;/*number为扫描到的常量*/c1=string[i-2];}SaveNumber[CharNumber]=number;/*将number存入到数组save_number中,下标为char_number*/*PreExpr++=c;CharNumber++;}else if((c>='a'&&c<='z')||(c>='A'&&c<='Z')){//string下一个字符不能为常量或变量,否则,出错if((string[i-1]>='0'&&string[i-1]<='9')||(string[i-1]>='A'&&string[i-1]<='Z')||(string[i-1]>='a'&&string[i-1]<='z')) {cout<<("\n输入的表达式有误!");return ERROR;}else *PreExpr++=c;}else if(c=='*'||c=='/'){/*字符为运算符'*'或'/'*/while(GetTop1(S,c1)&&(c1=='^')){Pop1(S,c1);*PreExpr++=c1;}/*如果c1比c优先,出栈*/Push1(S,c);/*入栈字符c*/}else if(c=='+'||c=='-'){/*字符为运算符'+'或'-'*/while(GetTop1(S,c1)&&(c1=='^'||c1=='*'||c1=='/')){Pop1(S,c1);*PreExpr++=c1;}/*如果c1比c优先,出栈*/Push1(S,c);/*入栈运算符c*/}else if(c=='^'){Push1(S,c);/*入栈运算符'^'*/}else {cout<<"\n输入的表达式有误!";return ERROR;}/*其他字符,错误,返回ERROR*/i--;/*下一个字符*/if(i>=0) c=string[i];/*i不小于0,c=string[i]循环下一个字符*/else /*否则,将清空栈*/while(!StackEmpty1(S)&&GetTop1(S,c1)&&c1!='#') {Pop1(S,c);*PreExpr++=c;} }Pop1(S,c);/*将'#'出栈*/*PreExpr='\0';/*字符串结束符*/if(i<0&&StackEmpty1(S)) return OK;else return ERROR;}/*将字符串exprstring反转过来*/void ReversalString(char *exprstring){len=strlen(exprstring);/*len为exprstring的长度*/for(i=0,j=len-1;i<j;i++,j--){/*字符串前后两个字符对换*/temp=exprstring[i];exprstring[i]=exprstring[j];exprstring[j]=temp;}}/*常数合并操作函数,合并表达式E中所有常数运算*/void MergeConst(BiTree *E){while((*E)->lchild&&(*E)->rchild){/*左右孩子不为空*/if((*E)->lchild->data.tag==INT&&(*E)->rchild->data.tag==INT){//假如左右孩子为常量,合并result=Operate((*E)->lchild->data.num,(*E)->data.c,(*E)->rchild->data.num);/*常数合并运算,调用Operate()函数求值*/(*E)->data.tag=INT;(*E)->data.num=result;/*修改之前的运算符为常量*/free((*E)->lchild);/*释放左孩子*/free((*E)->rchild);/*释放右孩子*/(*E)->lchild=(*E)->rchild=NULL;/*左右孩子置空*/}else{MergeConst(&((*E)->lchild));/*递归左孩子*/MergeConst(&((*E)->rchild));/*递归右孩子*/}}}//判断是否操作符int IsOperator(char c){switch(c){case '+': return TRUE;case '-': return TRUE;case '*': return TRUE;case '/': return TRUE;case '^': return TRUE;default: return FALSE;}}void Diff(BiTree &E,char v)//求偏导数{if((E->lchild)&&(E->rchild))//树不为空{if((E->rchild->data.c=='^')&&(E->rchild->lchild->data.c==v) )//若该变量为要求偏导的变量,则对其求偏导{E->lchild->data.num=(E->lchild->data.num)*(E->rchild->rchild->data.num);E->lchild->data.tag=INT;E->rchild->rchild->data.num=E->rchild->rchild->data.num-1;}else if(E->rchild->data.tag==INT&&(E->data.c=='+'||E->data.c=='-'))//若该变量不是要求偏导的变量,且为整数,则以0替换其中数据{E->rchild->data.num=0;E->rchild->data.tag=INT;}else if((E->rchild->data.c==v)&&(IsOperator(E->lchild->data.c)))//否则以1替换其中数据{E->rchild->data.num=1;E->rchild->data.tag=INT;}else if((E->rchild->data.c==v)&&E->lchild->data.tag==INT){E->data.num=E->lchild->data.num;E->data.tag=INT;free(E->lchild);free(E->rchild);E->lchild=E->rchild=NULL;}Diff(E->lchild,v);//递归执行左子树Diff(E->rchild,v);//递归执行右子树}else return;}3.主程序和其他函数:char menu()//主菜单{char choice;cout<<"\n\t****************************************";cout<<"\n\t***********9.表达式类型的实现***********";cout<<"\n\t 1 >>>输入正确的前缀表达式";cout<<"\n\t 2 >>>带括弧的中缀表示式输出";cout<<"\n\t 3 >>>对变量进行赋值";cout<<"\n\t 4 >>>对算数表达式求值";cout<<"\n\t 5 >>>构造一个新的复合表达式";cout<<"\n\t 6 >>>以表达式的原书写形式输入(选作)";cout<<"\n\t 7 >>>合并表达式中所有常数运算(选作)";cout<<"\n\t 8 >>>三角函数操作 (选作)";cout<<"\n\t 9 >>>求偏导数 (选作)";cout<<"\n\t 0 >>>退出";cout<<"\n\t****************************************";cout<<"\n\t请输入你的选择(数字)>>>>>";cin >> choice;return choice;}int main(){BiTree E,E1;//两个表达式E和E1int flag=0;//表达式E构造标志,为0表示未构造,为1表示已构造char V,P;//V被赋值,P为符合表达式运算符char string[30],ExprString[30];//字符串while(TRUE){system("cls");//清屏switch(menu()) {case '1':/*1 >>>输入正确的前缀表达式*/cout<<"\n\t*************************输入提示信息************************";cout<<"\n\t输入正确的前缀表达式的要求:";cout<<"\n\t\t【变量】 a-z或A-Z";cout<<"\n\t\t【常量】 0-9,不能超过9";cout<<"\n\t\t【运算符】 +,-,*,/,^";cout<<"\n\t请输入正确的前缀表达式,后按回车键存入缓冲区,否则可能会出错!";cout<<"\n\t*************************************************************";if(InputExpr(ExprString,0))//在flag=0时,初始输入if(ReadExpr(&E,ExprString)){//前缀读入并构造Eflag=1;cout<<"\n表达式构造成功!请按任意键返回菜单";}getchar();break;case '2':/*2 >>>带括弧的中缀表示式输出*/if(flag==1){cout<<("\n\t带括弧的中缀表达式为:");WriteExpr(E);}else cout<<("\n\t表达式未构造成功!请重新构造成功的表达式!");getchar();getchar();break;case '3':/*3 >>>对变量进行赋值*/cout<<("\n\t********************赋值操作说明信息***********************************");cout<<("\n\t赋值操作:实现对表达式中的某一个变量V的赋值,即使V=C,C为一整数");cout<<("\n\t 【1】根据输出的表达式,输入要赋值的变量V,只能输入一个字符,否则出错");cout<<("\n\t 【2】输入要将变量V赋值为的整数C,只能是整数,否则出错");cout<<("\n\t 【注】如果表达式未构造,请回到主菜单选择构造表达式");cout<<("\n\t***********************************************************************");if(flag==1){int AssignFlag=0;cout<<"\n表达式E为:";WriteExpr(E);fflush(stdin);/*清理缓冲区*/cout<<"\n请输入要赋值的字符:";V=getchar();cout<<"请输入要将赋值为:";cin>>c;Assign(&E,V,c,&AssignFlag);//赋值并改变标志if(AssignFlag){cout<<"\n赋值成功!\n赋值后的表达式为:";WriteExpr(E);}else cout<<"\n表达式里没有%c这个变量!",V;}else cout<<"\n表达式未构造成功!请构造成功的表达式!";getchar();getchar();break;case '4':/*4 >>>对算数表达式求值*/cout<<"\n\t********************算数表达式求值说明信息************************";cout<<"\n\t 【注】如果表达式还有变量未赋值,即表达式不是算数表达式";cout<<"\n\t 不能求出表达式的值,请回到主菜单选择赋值操作,后再求值";cout<<"\n\t******************************************************************";if(flag==1){cout<<"\n算数表达式:";WriteExpr(E);if(Check(E)){ //检查是否全赋值result=Value(E);cout<<"\n求算数表达式的值:\t";WriteExpr(E);cout<<"="<<result;}}else cout<<"\n表达式未构造成功!请构造成功的表达式!";getchar();getchar();break;case '5':/*5 >>>构造一个新的复合表达式*/cout<<"\n\t*****************构造新的复合表达式说明信息***************************";cout<<"\n\t 【1】构造一个新的表达式E1,采用表达式的原书写形式输入";cout<<"\n\t 【2】构造表达式E1成功后,输入要复合表达式E和E1的操作运算符(+,-,*,/,^)";cout<<"\n\t 【注】如表达式E未构造,不能复合表达式;如构造表达式E1错误,复合失败";cout<<"\n\t***********************************************************************";if(flag==1){cout<<"\n表达式E1为:";WriteExpr(E);cout<<"\n请构造新的表达式E2:";fflush(stdin);/*清理缓冲区*/if(InputExpr(string,1)){//标志为1,输入字符串if(ReadInorderExpr(string,ExprString)){//入栈ReversalString(ExprString);//反转if(ReadExpr(&E1,ExprString)){flag=1;cout<<("\n表达式E2构造成功!");WriteExpr(E1);cout<<("\n请输入要构造新的复合表达式的操作运算符>>>");P=getchar();while(P!='*'&&P!='/'&&P!='+'&&P!='-'&&P!='^'){fflush(stdin);/*清理缓冲区*/cout<<"\n输入的操作运算符有误!请重新输入>>>";P=getchar();}CompoundExpr(P,E,E1);}else cout<<"\n复合新的表达式失败!请按任意键返回主菜单!";}}}else cout<<"\n表达式未构造成功!请构造成功的表达式!";getchar();getchar();break;case '6':/*6 >>>以表达式的原书写形式输入*/cout<<"\n\t*************以表达式的原书写形式输入说明信息************************";cout<<"\n\t输入正确的原书写形式表达式";cout<<"\n\t 【变量】 a-z或A-Z";cout<<"\n\t 【常量】大于等于0的正整数";cout<<"\n\t 【运算符】 +,-,*,/,^(乘幂)";cout<<"\n\t 【括弧】左括弧 ( ,右括弧 ) ";cout<<"\n\t 【注】表示式中常量最多只能是30个,超过30个,出错!";cout<<"\n\t按原书写形式输入中,请按照正确的方式输入,否则可能会出错!";cout<<"\n\t**********************************************************************";if(InputExpr(string,1))if(ReadInorderExpr(string,ExprString)){ReversalString(ExprString);if(ReadExpr(&E,ExprString)){flag=1;cout<<"\n表达式构造成功!\n输入的带括弧的中缀表达式:";WriteExpr(E);}}getchar();getchar();break;case '7':/*7 >>>合并表达式中所有常数运算*/cout<<"\n***************合并表达式中的所有常数运算*******************************";cout<<"\n 【注】合并表达式中的所有常数运算并不能一次性将常数都合并!";cout<<"\n例如:表达式'1+2*(3+3*4+9/3)'的常数合并,选择7进行合并,结果变为\n'1+2*(3+12+3)',";cout<<"根据优先级先后合并的,如果要合并到最后,需多次选择7\n进行合并,又合并一次'1+2*(15+3)',";cout<<"再次合并'1+2*18',再次合并'1+36',\n再次合并'37',后无法合并!";cout<<"\n************************************************************************";if(flag==1) {cout<<"\n原表达式为:";WriteExpr(E);MergeConst(&E);//常数合并操作cout<<"\n合并表达式中所有的常数运算后的表达式:";WriteExpr(E);}else cout<<"\n表达式未构造成功!请构造成功的表达式!";getchar();getchar();break;case '8'://三角函数操作cout<<"\t***************************三角函数操作(选作)***************************";cout<<"\n";cout<<"\n\t[注] 请按要求输入其中 s代表sin c代表cos t代表tan ";cout<<"\n\t角度用弧度表示,例如~1 即表示sin 1";cout<<"\n\t本操作只可求三角函数值,如需其他操作请将结果带入其它操作中";cout<<"\n\t输入一个字符请按回车,确保正确录入";cout<<"\n\t************************************************************************";double opr1,result1;char opr;cout<<"\n请按要求输入";cin>>opr;cin>>opr1;result1=Operate1(opr,opr1);cout<<"结果为:"<<result1;getchar();getchar();break;case '9'://求导getchar();char h;cout<<"输入需要求偏导的变量字符\n";cin>>h;Diff(E,h);WriteExpr(E);getchar();getchar();break;case '0':/*0 >>>退出*/cout<<"\n请按任意键退出!";getchar();getchar();exit(0);break;default :cout<<"\n输入有误!请按任意键回到主菜单重新选择!";getchar();getchar();getchar();//Sleep(5000);break;}}return 0;}(部分代码较长,故在word文档中较难整理格式,请参见附录源代码查看)函数调用关系:四.调试分析1.合并表达式所有常数运算功能一开始只能实现一次合并,即:1+4*6=1+24 或者8+3*2^4=8+3*16。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档