数据结构与算法实验

本文是自己数据结构与算法的实验作业,只为了便于自己查看和学习,有问题的地方还望斧正,所用软件为devc++,以下代码拿去都能直接运行。

目录

1. VC 编程与测试初步

2. 实现顺序表的各种基本运算

3. 实现单链表的各种基本运算

4. 线性表及其应用-----约瑟夫环

5. 栈与队列的各种基本运算

6. 栈与队列应用(I)-----算术表达式求值

7. 栈与队列应用(II)----迷宫问题

8. 实现串的各种基本运算


 

 

1. VC 编程与测试初步

1.1 熟悉 VC++编程运行环境.
1.2 设计一个程序 exp1-1.cpp,输出所有小于等于 n(n 为一个大于 2 的
正整数)的素数.要求: ( 1 ) 每行输出 10 个素数; ( 2 ) 尽可能采用较优
的算法.
#include<stdio.h>
#include<math.h>
bool sushu(int n){
	for(int i=2;i<=(int)sqrt(n);i++){
		if(n%i==0){
			return 0;
		}
	}
	return 1;
}
bool sushu(int n);//判断是否为素数,是素数返回1,不是返回0 
int main(void)
{
    int n;
    int count = 0;//用于统计素数个数 
    printf("请输入一个大于2的数字\n");
    scanf("%d",&n);
//遍历小于n,大于2的所有数字 
	for(int i=2;i<=n;i++){
		if(sushu(i)){//判断是否为素数 
			printf("%d ",i);//如果为素数,则大于出来 
			count++;
			if(count%10==0){//为10个时,打印换行符号 
				printf("\n");
			}
			
		}
	}
}

2. 实现顺序表的各种基本运算

编写一个程序 algo2-1.cpp,实现顺序表的各种基本运算(假设顺序表的
元素类型为 char),并在此基础上设计一个程序 exp2-1,完成如下功能:
( 1 ) 初始化顺序表 L;
( 2 ) 采用尾插法依次插入元素 a, b, c, d, e;
( 3 ) 输出顺序表 L;
( 4 ) 输出顺序表 L 长度;
( 5 ) 判断顺序表 L 是否为空;
( 6 ) 输出顺序表 L 的第 3 个元素;
( 7 ) 输出元素 a 的位置;
( 8 ) 在第 4 个元素位置上插入元素 f;
( 9 ) 输出顺序表 L;
( 10 ) 删除 L 的第 3 个元素;
( 11 ) 输出顺序表 L;( 12 ) 释放顺序表 L;
#include <stdio.h> 
#include <malloc.h>
#define MaxSize 50
typedef char ElemType;
typedef struct 
 {
	ElemType data[MaxSize];          //存放顺序表中的元素
	int length;                      //存放顺序表的长度
} SqList;

//初始化线性表
void InitList(SqList *&L) {
	L=(SqList *)malloc(sizeof(SqList)); //分配存放 线性表的内存
	L->length=0; //使空线性表长度为0 
}


//销毁顺序表
void DestroyList(SqList *&L) {
	free(L);//释放L的内存 
}
//判断顺序表是否为空
bool ListEmpty(SqList *L) {
	return (L->length==0);//线性表长度为0就是空表 
}
//求线性表的长度 
int ListLength(SqList *L) {
	return(L->length);//L的长度即可 
}
//打印线性表
void DispList(SqList *L) {
	for(int i=0;i<L->length;i++){//遍历顺序表打印各元素值 
		printf("%c",L->data[i]);
	}
	printf("\n");
}
//尾插法
bool pushback(SqList *&L, ElemType date)
{
	if (L->length==MaxSize) {
	return (false);}
    else L->data[L->length++] = date;
} 
//求顺序表中的某个元素
bool GetElem(SqList *L,int i,ElemType &e) {
	if(i<i||i>L->length)//输入位置小于1或者大于顺序表长度时返回false 
		{return false;}
	e=L->data[i-1];
	return true;//否则返回值 
}
//按元素值查找,返回位置
int LocateElem(SqList *L,ElemType e) {
	int i=0;
	while(i<L->length&&L->data[i]!=e){//当i小于L的长度或者未找到匹配的值时 ,则一直遍历 
		i++;
	}
	if(i>=L->length) {//未找到时返回false 
		return false;
	}
	else{
		return i+1;//找打返回其逻辑顺序 
	}
}
//插入数据元素
bool ListInsert(SqList *&L,int i, ElemType e) {
	
	if (i<1||i>L->length||L->length==MaxSize) {//如果插入的位置小于1,或者插入的位置大于L的长度,或者顺序表已经表满了,返回false 
		return false;
	}
	i--;//将逻辑序号转化为物理序号
	for (int j=L->length;j>i;j--) {//将data[i]及后面的元素后移一个位置 
		L->data[i]=L->data[j-1];
	}
	L->data[i] =e;//插入元素e
	L->length++;//顺序表长度加1 
	return true;//成功插入返回true 
}
//删除数据元素
bool ListDelete(SqList *&L,int i,ElemType &e) {
	if (i<1||i>L->length){//参数i错误返回false 
		return false;
	}
	i--;//将顺序逻辑转换为物理逻辑
	e=L->data[i] ;//将删除的元素保存道e里面 
	for(int j=i;j<L->length-1;j++) {//将data[i]后面的元素向前移动一位 
		L->data[j]=L->data[j+1];
	}
	L->length--;//顺序表长度减1 
	return true; //成功删除返回true 
}
void InitList(SqList *&L);//初始化线性表,构造一个空的线性表L 
void DestroyList(SqList *&L);//销毁线性表,释放线性表L占用内存空间 
bool ListEmpty(SqList *L);//判断线性表是否为空表,若L为空表,则返回真,否则返回假 
int ListLength(SqList *L);//求线性表的长度,返回L中元素的个数 
void DispList(SqList *L);//输出线性表,当线性表L不为空时顺序显示L中各结点的值域 
bool GetElem(SqList *L,int i,ElemType &e);//求线性表中某个数据元素值,用e返回L中第i(1<=i<=n)个元素的值 
int LocateElem(SqList *L,ElemType e);//按元素值查找,返回L中第一个值域与e相等的元素的序号,若这样的元素不存在,则返回值为0 
bool ListInsert(SqList *&L,int i,ElemType e);//插入数据元素,在L的第i(1 <=i<=n)个位置插入一个新的元素e,L的长度增1 
bool ListDelete(SqList *&L,int i,ElemType &e);//删除数据元素,删除L的第i(1<=i<=n)个元素,并用e返回其值,L的长度减1 
bool pushback(SqList *&L,ElemType date);//尾插法,若线性表未满,则在尾部插入data,长度加1,否则返回假 
int main(){
	char e,a;
	SqList *L;
	//(1)初始化顺序表L 
	InitList(L);
	//(2)采用尾插法依次插入元素a,b,c,d 
	pushback(L,'a');
	pushback(L,'b');
	pushback(L,'c');
	pushback(L,'d');
	//(3)输出顺序表L 
	printf("顺序表L:");
	DispList(L);
	//(4)输出顺序表L长度 
	printf("顺序表L的长度:");
	printf("%d\n",ListLength(L));
	//(5)判断顺序表L是否为空 
	printf("顺序表L是否为空:"); 
	printf("%d\n",ListEmpty(L));
	//(6)输出顺序表L的第三个元素 
	if(GetElem(L,3,a)) {
		printf("顺序表L的第三个元素为:%c\n",a);
	}else{
		printf("顺序表不存在第三个元素"); 
	}
	//(7)输出元素a的位置 
	printf("元素a的位置:%d\n",LocateElem(L,'a'));
	//(8)在第4个元素位置插入元素f 
	ListInsert(L,4,'f');
	//(9)输出顺序表L 
	printf("插入元素后的顺序表L:"); 
	DispList(L);
	//(10)删除L的第3个元素 
	printf("删除元素后的顺序表L:");
	ListDelete(L,3,e);
	//(11)输出顺序表L 
	DispList(L);
	//(12)释放顺序表L 
	DestroyList(L);//销毁顺序表 
}

3. 实现单链表的各种基本运算

编写一个程序 algo2-2.cpp,实现单链表的各种基本运算(假设单链表的
元素类型为 char),并在此基础上设计一个程序 exp2-2,完成如下功能:
( 1 ) 初始化单链表 L;
( 2 ) 采用尾插法依次插入元素 a, b, c, d, e;
( 3 ) 输出单链表 L;
( 4 ) 输出单链表 L 长度;
( 5 ) 判断单链表 L 是否为空;
( 6 ) 输出单链表 L 的第 3 个元素;
( 7 ) 输出元素 a 的位置;
( 8 ) 在第 4 个元素位置上插入元素 f;
( 9 ) 输出单链表 L;
( 10 ) 删除 L 的第 3 个元素;
( 11 ) 输出单链表 L;
( 12 ) 释放单链表 L;
#include<stdio.h>
#include<malloc.h>
typedef char ElemType;
typedef struct LNode {//本名
	int data;    //数据域
	struct LNode* next; //指针域
}LinkNode;//别名,LinkList代表表头
//初始化链表
void InitList(LinkNode *&L) {
	L=(LinkNode *)malloc(sizeof(LinkNode));//分配内存 
	L->next=NULL;//创建头节点,其next指向null 
}
//销毁链表 
void DestroyList(LinkNode *&L){
	LinkNode *pre=L,*p=L->next;//pre指向节点p的前驱节点 
	while (p!=NULL){//扫描单链表L 
		free(pre);//释放pre节点
		pre=p;//pre,p同步后移一个节点 
		p=pre->next;
	}
	free(pre);//循环结束时p为NULL,pre指向未节点,释放它 
}
//判断链表是否未空
bool ListEmpty(LinkNode *L) {
	return (L->next==NULL);//头节点的后驱节点为空则是空链表 
}
//求链表长度
int ListLength(LinkNode *L) {
	int n=0;//计数(记录长度) 
	LinkNode *p=L;//p指向头节点 
	while (p->next!=NULL){//遍历结点 
		n++;
		p=p->next;
	}
	return (n);//循环结束,p指向尾结点,返回个数(长度)n 
}
//打印链表
void DispList(LinkNode *L){
	LinkNode *p=L->next;//p指向头节点 
	while (p!=NULL){//p不为NULL,输出p结点的data项 
		printf("%c",p->data);
		p=p->next;//p移向下一个结点 
	}
	printf("\n");
}  
//求线性表中的某个数据元素
bool GetElem(LinkNode *L,int i,ElemType &e){
	int j=0;
	LinkNode *p=L;//p指向头节点,j置为0(即头结点的序号为0) 
	if(i<=0) {	//i错误返回false 
		return false;
	}
	while (j<i&&p!=NULL){//找第i个结点 
		j++;
		p=p->next;
	}
	if (p==NULL){//不存在第i个数据结点,返回false 
		return false;
	}else{//存在第i个数据结点,返回true 
		e=p->data;
		return true;
	}
} 
//按元素值查找
int LocateElem(LinkNode *L,ElemType e) {
	int i=1;
	LinkNode *p=L->next;//p指向头结点,i置为1(即头结点的序号为1) 
	while(p!=NULL&&p->data!=e){//查找data值为e的结点,其序号为i 
		p=p->next;
		i++;
	}
	if(p==NULL){//不存在值为e的结点时返回0 
		return 0;
	}else{//存在值为e的结点时返回其逻辑序号 
		return i;
	}
}
//插入数据元素
bool ListInsert(LinkNode *&L,int i,ElemType e) {
	int j=0;
	LinkNode *p=L,*s;//p指向头结点,j置为0(即头结点的序号为0) 
	if(i<=0){//i错误时返回false 
		return false;
	}
	while (j<i-1&&p!=NULL){//查找第i-1个结点p (即插入的位置) 
		j++;
		p=p->next;
	}
	if(p==NULL) {//未找到第 i-1个结点时,返回false 
		return false;
	}else{
		s=(LinkNode *)malloc(sizeof(LinkNode));
		s->data=e;//创建新节点是,其data为e 
		s->next=p->next;//将结点s插入到结点p之后 
		p->next=s;
		return true;
	}
}
//删除数据元素
bool ListDelete (LinkNode *&L,int i,ElemType &e) {
	int j=0;
	LinkNode *p=L,*q;//p指向头结点,j置为0(即头结点序号为0) 
	if(i<=0){//i错误时返回false 
		return false;
	}
	while (j<i-1&&p!=NULL){//查找第i-个结点 
		j++;
		p=p->next;
	}
	if (p==NULL){//未找到第i-个结点时返回false 
		return false;
	}else{//找到第i-1个结点怕p 
		q=p->next;//q指向第i个结点 
		if(q==NULL){//若不存在第i个结点则返回false 
			return false;
		}
		e=q->data;
		p->next=q->next;//从单链表中删除q结点 
		free(q);//释放q结点 
		return true;//返回true表示成功删除第i个结点 
	}}
//尾插法
void CreateListR(LinkNode *&L, ElemType a[],int n){
	LinkNode *s,*r;
	L=(LinkNode *)malloc(sizeof(LinkNode));//创建头结点 
	r=L;//r始终指向尾结点,初始时指向头结点 
	for (int i=0;i<n;i++){//循环建立数据结点 
		s=(LinkNode *)malloc(sizeof(LinkNode));//分配内存地址 
		s->data=a[i];//创建数据结点s 
		r->next=s;//将结点s插入到结点r之后 
		r=s;
	}
	r->next=NULL;//尾结点的next域置为NULL 
}  
void InitList(LinkNode *&L);//初始化线性表,构造一个空的线性表L 
void DestroyList(LinkNode *&L);//销毁线性表,释放线性表L占用的内存空间 
bool ListEmpty(LinkNode *L);//判断线性表是否为空表,若L为空表,则返回真,否则返回假 
int ListLength(LinkNode *L);//求线性表的长度,返回L中的元素个数 
void DispList(LinkNode *L);//输出线性表,当线性表L不为空时顺序显示L中个结点的值域 
bool GetElem(LinkNode *L,int i,ElemType &e);//求线性表中某个数据元素值,用e返回L中第i(1<=1<=n)个元素的值 ,参数错误返回0 
int LocateElem(LinkNode *L,ElemType e);//按元素值查找,返回L中第一个值域与e相等的元素的序号,若这样的元素不存在,则返回值为0 
bool ListInsert(LinkNode *&L,int i,ElemType e);//插入数据元素,在L的第i(1<=i<=n+1)个位置插入一个新的元素e,L的长度增1 
bool ListDelete (LinkNode *&L,int i,ElemType &e);//删除数据元素,删除L的第i(1<=i<=n)个元素,并用e返回其值,L的长度减1 
void CreateListR(LinkNode *&L, ElemType a[],int n);//在顺序表L尾部插值,将数组a中的元素(n个)依次读取,然后插入到顺序表L的尾部 
int main(){
	LinkNode *L;
	ElemType e,a; 
	ElemType arr[5]={'a','b','c','d','e'};
	//(1)初始化单链表L 
	InitList(L);
	//(2)采用尾插法依次插入元素a,b,c,d,e 
	CreateListR(L,arr,5);
	//(3)输出单链表L 
	printf("单链表L:") ;
	DispList(L);
	//(4)输出单链表的长度 
	printf("单链表L的长度:%d\n",ListLength(L));
	//(5)判断单链表是否为空 
	printf("单链表L是否为空:%d\n",ListEmpty(L));
	//(6)输出单链表L的第三个元素 
	if(GetElem(L,3,e)){
		printf("单链表L的第三个元素为:%c\n",e); 
	}else{
		printf("参数错误,不存在这个元素\n");
	} 
	//(7)输出元素a的位置 
	if(LocateElem(L,'a')){
		printf("元素a的位置:%d\n",LocateElem(L,'a'));
	}else{
		printf("不存在该个元素\n"); 
	}
	//(8)在第4个元素位置插入元素f 
	ListInsert(L,4,'f');
	//(9)输出单链表L
	printf("插入操作后的单链表L:") ;
	DispList(L);
	//(10)删除L的第3个元素 
	ListDelete(L,3,a);
	//(11)输出单链表L 
	printf("删除操作后的单链表L:") ;
	DispList(L);
	//(12)释放单链表L 
	DestroyList(L);
	}

4. 线性表及其应用-----约瑟夫环

( 1 ) 问题描述:约瑟夫问题的一种描述为,编号为 1,2,3,……n 的 n
个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。一开始
任选一个正整数作为报数上限值 m,从第一个人开始按顺时针方向自1 开始顺序报数,报到 m 时停止报数。报 m 的人出列,将他的密码作
为新的 m 的值,从他在顺时针方向上的下一个人开始重新从 1 报数,
如此下去,直至所有的人全部出列为止。试设计一个程序求出出列顺
序。
( 2 ) 基本操作:利用单向循环链表存储结构模拟此过程,按照出列
的顺序印出各人的编号。
( 3 )测试数据:m 的初值为 20;n=7,7 个人的密码依次为:
3,1,7,2,4,8,4,首先 m 值为 6(正确的出列顺序应为 6,1,4,7,2,3,5)。
( 4 )实现提示:程序运行后,首先要求用户指定初始报数上限值,
然后读取各人的密码。可设 n≤30。此题所用的循环链表中不需要“头
结点”,请注意空表和非空表的界限。
#include<stdio.h>
#include<stdlib.h>
typedef int ElemType;
typedef struct LNode{
	int number;//存放序号 
	ElemType data;//存放数据值(密码值) 
	struct LNode *next;//指向后继结点 
} LinkList;//单链表结点类型 
//尾插法插入元素 
void CreatList(LinkList *&L,int n){
	LinkList *R = L,*S;//R用于存放循环链表尾结点的位置 
	ElemType c;
	printf("请输入第1个人的密码:\n");//建立首元结点 
	scanf("%d",&c); 
	L->number = 1;
	L->data = c; 
	for(int i = 2;i <= n;i++){
		printf("请输入第%d个人的密码:\n",i);
		scanf("%d",&c);
		S = (LinkList * )malloc(sizeof(LinkList));
		S->number = i;
		S->data = c;
		R->next = S;
		R = S;//利用尾插法构造链表 
	} 
	R->next = L;//尾结点的指针指向首元结点 建立循环链表 
} 
//初始化首结点 
void InitList(LinkList *&L) {
	L=(LinkList *)malloc(sizeof(LinkList));
	L->next=NULL;//创建头结点,其next域置为NULL 
}
void InitList(LinkList *&L);//初始化头结点L
void CreatList(LinkList *&L,int n);//尾插法将n个元素插入链表L,同时将L的尾结点指向头结点,构成一个循环单链表 
int main(){
	int m, n;
	LinkList *L, *p, *q;
	InitList(L);//建立首结点 
	printf("请输入人数 n:\n");
	scanf("%d",&n);
	printf("请输入报数上限值 m:\n");
	scanf("%d",&m);
	CreatList(L,n);
	p = L;
	while(p->next!=p){//当链表长度大于1时 
		for(int i = 1;i < m;i++){//找到m时的结点p 
			q = p;//q为p的前驱结点
			p = p->next;
		}//找到报数m的结点 
		m = p->data;
		printf("编号为%d的人出列。\n",p->number);
		q->next = p->next;
		free(p);//删除p结点 
		p = q->next;
	}
	printf("编号为%d的人出列。\n",p->number);//最后一个结点出列 
	free(q); //删除最后一个结点 
	return 0;
}

5. 栈与队列的各种基本运算

编写一个程序 algo3-1.cpp,实现顺序(链)栈(假设栈中元素类型为 char)
的各种基本运算,并在此基础上设计两个程序 exp3-1.cpp(顺序
栈) ,exp3-2.cpp(链栈),完成如下功能:
( 1 ) 初始化栈 s;
( 2 ) 判断栈 s 是否非空;
( 3 ) 依次进栈元素 a, b, c, d, e;
( 4 ) 判断栈 s 是否非空;
( 5 ) 输出栈长度;( 6 ) 输出从栈顶到栈底元素;
( 7 ) 输出出栈序列;
( 8 ) 判断栈 s 是否非空;
( 9 ) 释放栈;
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 50
typedef char ElemType;
typedef struct linknode
{
	ElemType data;//数据域 
	struct linknode * next; //指针域 
 } LinkStNode;//链栈节点类型 
void InitStack (LinkStNode *&s){
 	s=(LinkStNode *)malloc(sizeof(LinkStNode));//分配地址 
 	s->next=NULL; 
 } 
void DestroyStack(LinkStNode *&s){
 	LinkStNode *pre=s,*p=s->next;//pre指向头结点,p指向首结点
	while(p!=NULL){//循到p为空 
		free(pre);//释放pre结点 
		pre=p;//pre,p同步后移 
		p=pre->next;
	} 
	free(pre);//此时pre指向尾结点,释放其空间 
 }
bool StackEmpty(LinkStNode *s){
 	return (s->next==NULL);
 } 
 void Push(LinkStNode *&s,ElemType e){
 	LinkStNode *p;
 	p=(LinkStNode *)malloc(sizeof(LinkStNode));//新建结点p 
 	p->data=e;//存放元素e 
 	p->next=s->next;//j将p结点插入作为首结点 
 	s->next=p;
 }
 bool Pop(LinkStNode *&s,ElemType &e){
 	LinkStNode *p;
 	if(s->next==NULL)//栈空的情况 
 		return false;//返回假 
 	p=s->next;//p指向首节点 
 	e=p->data;//提取首节点的值 
 	s->next=p->next;//删除首节点
	free(p);//释放被删除结点的存储空间
	return true;//返回2真 
 } 
 bool GetTop(LinkStNode *s,ElemType &e){
 	if(s->next==NULL)//栈空的情况 
 		return false;//返回假 
 	e=s->next->data;//提取首节点值 
 	return true;//返回真 
 } 
 void DispStack (LinkStNode *s ) {
	while (!StackEmpty(s) ) {
		ElemType e;
		Pop(s,e);
		printf ("%c", e);
	}
	printf("\n");
}
//输出链表(栈顶到栈底) 
void DispList(LinkStNode *L){
	LinkStNode *p=L->next;//p指向头节点 
	while (p!=NULL){//p不为NULL,输出p结点的data项 
		printf("%c",p->data);
		p=p->next;//p移向下一个结点 
	}
	printf("\n");
}  
//求链表长度 
int ListLength(LinkStNode *L) {
	int n=0;//计数(记录长度) 
	LinkStNode *p=L;//p指向头节点 
	while (p->next!=NULL){//遍历结点 
		n++;
		p=p->next;
	}
	return (n);//循环结束,p指向尾结点,返回个数(长度)n 
}
 int ListLength(LinkStNode *L);//求线性表的长度,返回L中的元素个数 
 void DispList(LinkStNode *s);//打印从栈顶到栈底的元素 
 void DispStack (LinkStNode *s );//打印出栈序列,此时栈已经为空 
 void InitStack(LinkStNode *&s);//初始化栈,构造一个空栈 
 void DestroyStack(LinkStNode *&s);//销毁栈,释放栈s占用的存储空间 
 bool StackEmpty(LinkStNode *s);//判断栈是否为空,若栈s为空,则返回真;否者返回假 
 void Push(LinkStNode *&s,ElemType e);//进栈,将元素e插入到栈s中作为栈顶元素 
 bool Pop(LinkStNode *&s,ElemType &e);//出栈,从栈s中删除栈顶元素,并将其值赋给e 
 bool GetTop(LinkStNode *s,ElemType &e);//取栈顶元素,返回当前的栈顶元素,并将其赋值给e
 int main(){
 	LinkStNode * s;
 	//(1)初始化栈s 
 	InitStack(s);
 	//(1)判栈s是否为空 
 	printf("栈s是否为空:%d\n",StackEmpty(s));
 	//(2)依次进栈元素a,b,c,d,e 
 	Push(s,'a');
 	Push(s,'b');
 	Push(s,'c');
 	Push(s,'d');
 	Push(s,'e');
 	//(4)判单栈是否为空 
 	printf("a,b,c,d,e依次入栈后") ;
 	printf("栈s是否空:%d\n",StackEmpty(s));
 	//(5)输出栈的长度
	printf("栈s的长度:%d\n",ListLength(s));
	//(6)输出从栈顶到栈底的元素
	printf("输出从栈顶到栈底的元素:") ;
 	DispList(s);
 	//(7)输出出栈序列 
 	printf("输出出栈序列:") ;
 	DispStack(s);
	//(8)判断栈s是否为空	
 	printf("栈s是否为空:%d\n",StackEmpty(s));
 	//(9)释放栈 
 	DestroyStack(s);
 } 

6. 栈与队列应用(I)-----算术表达式求值

(1)问题描述:表达式计算是实现程序设计语言的基本问题之一,
也是栈的应用的一个典型的例子。设计一个程序,演示用算符优先法
对算术表达式求值的过程。
(2)基本要求:以字符序列的形式从终端输入语法正确的、不含变
量的整数表达式。利用教科书表3.1给出的算符优先关系,实现对算
术四则混合运算表达式的求值,并仿照教科书的例3-1演示在求值中
运算符栈、运算数栈、输入字符和主要操作的变化过程。
(3)测试数据:教科书例3-1的算术表达式3*(7-2),以及下列表达式8;
1+2+3+4 ;
88-1*5 ;
1024/4*8 ;
(20+2)*(6/2) ;
3-3-3 ;
8/(9-9) ;
2*(6+2*(3+6*(6+6)));(((6+6)*6+3)*2+6)*2;
#include<stdio.h>
#include <malloc.h> 
#include <cstdlib>
#define MaxSize 50
typedef char ElemType;
typedef struct{
	char data[MaxSize];//存放栈中的数据元素 
	int top;//栈顶指针,即存放栈顶元素在data数组中的下标 
}SqStack;//顺序栈类型 
typedef struct{
	double data[MaxSize];//存放栈中的数据元素 
	int top;//栈顶指针,即存放栈顶元素在data数组中的下标 
}SqStack1;//顺序栈类型 
void InitStack(SqStack *&s){
	s=(SqStack *)malloc(sizeof(SqStack));//分配一个顺序栈空间,首地址存放在s中 
	s->top=-1;//栈顶指针置为-1 
}
void InitStack1(SqStack1 *&s){
	s=(SqStack1 *)malloc(sizeof(SqStack1));//分配一个顺序栈空间,首地址存放在s中 
	s->top=-1;//栈顶指针置为-1 
}
void DestroyStack(SqStack *&s) {
	free(s);
}
void DestroyStack1(SqStack1 *&s) {
	free(s);
}
bool StackEmpty1(SqStack *s){
	return (s->top==-1);
}
bool StackEmpty(SqStack *s){
	return (s->top==-1);
}
bool Push(SqStack *&s,char e){
	if(s->top==MaxSize-1)//栈满的情况,即栈上溢出 
		return false;
	s->top++;//栈顶指针增1 
	s->data[s->top]=e;//元素e放在栈顶指针处 
	return true; 
}
bool Pop(SqStack *&s,char &e) {
	if (s->top==-1)//栈空的情况,即栈下溢出
		return false;
	e=s->data[s->top] ;//取栈顶指针 
	s->top--;//栈顶指针减1 
	return true;
}
bool GetTop(SqStack *s,char &e) {
	if (s->top==-1)//栈为空的情况,即栈下溢出
		return false;
	e=s->data[s->top] ;//取栈顶元素  
	return true;
}
bool Push1(SqStack1 *&s,double e){
	if(s->top==MaxSize-1)//栈满的情况,即栈上溢出 
		return false;
	s->top++;//栈顶指针增1 
	s->data[s->top]=e;//元素e放在栈顶指针处 
	return true; 
}
bool Pop1(SqStack1 *&s,double &e) {
	if (s->top==-1)//栈空的情况,即栈下溢出
		return false;
	e=s->data[s->top] ;//取栈顶指针 
	s->top--;//栈顶指针减1 
	return true;
}
bool GetTop1(SqStack1 *s,double &e) {
	if (s->top==-1)//栈为空的情况,即栈下溢出
		return false;
	e=s->data[s->top] ;//取栈顶元素  
	return true;
}
double compvalue (char * postexp){
	double d,a,b,c,e;
	SqStack1 *Opnd;//定义操作数栈 
	InitStack1(Opnd);//初始化操作栈
	while (*postexp!='\0') {//postexp字符串未扫描完时循环 
		switch(*postexp){
			case '+'://判定为+号 
				Pop1(Opnd,a);//出栈元素a 
				Pop1(Opnd,b);//出战元素b 
				c=b+a;//计算c 
				Push1(Opnd,c);//将计算结果c入栈 
				break;
			case '-'://判定为-号 
				Pop1(Opnd,a);//出栈元素a 
				Pop1(Opnd,b);//进栈元素b 
				c=b-a;//计算c 
				Push1(Opnd,c);//将计算结果c进栈 
				break;
			case '*':
				Pop1(Opnd,a);//出栈元素a 
				Pop1(Opnd,b);//出栈元素b 
				c=b*a;//计算c 
				Push1(Opnd,c);//将计算结果c进栈 
				break;
			case '/'://判定为/号 
				Pop1(Opnd,a);//出栈元素a 
				Pop1(Opnd,b);//出栈元素b 
				if(a!=0){//防止除零错误 
					c=b/a;//计算c 
					Push1(Opnd,c);//将计算结果c进栈 
					break;
				}else{
					printf("除零错误!返回值为0:");
					return false;//异常退出 
				}
				break;
			default://处理数字字符 
			d=0;//将连续的数字字符转换成对应的数值存放到d中 
			while (* postexp>='0'&&*postexp<='9'){//判定为数字字符 
				d=10*d+*postexp-'0';
				postexp++;
			}
			Push1(Opnd,d);//将数值d进栈 
			break;
		}
		postexp++;//继续处理其他字符 
	}
	GetTop1(Opnd,e);//取栈顶元素 
	DestroyStack1(Opnd);//销毁栈 
	return e;//返回e 
} 
void trans(char *exp,char postexp[]){//将算术表达式exp转换成后缀表达式postexp 
	char e;
	SqStack *Optr;  //定义运算符栈指针
	InitStack(Optr) ;//初始化运算符栈
	int i=0;//i作为postexp的下标
	while(*exp!='\0') {//exp表达式未扫描完时循环
		switch(*exp) {
			case '(' ://判定为左括号
				Push(Optr,'(') ;//左括号进栈
				exp++;//继续扫描其他字符 
				break; 
			case ')' ://判定为右括号 
				Pop(Optr,e);//出栈元素e
				while (e!='(') {//e不为右括号时循环 
					postexp[i++]=e;//将e存放到postexp中
					Pop(Optr,e) ;//继续出栈元素e 
				}
				exp++;
				break;
			case '+' ://判定为加或者减号
			case '-' :
				while (!StackEmpty(Optr)){//栈不空循环 
					GetTop(Optr,e);//取栈顶元素e 
					if (e!='('){//e不是左括号 
						postexp[i++]=e;//将e存放到postexp中 
						Pop(Optr,e);//出栈元素e 
					}else{//e是右括号时退出循环 
						break;
					}
				}
				Push(Optr,*exp);//将+或-进栈 
				exp++;//继续扫描其他字符 
				break;
			case '*'://判定*灬/号 
			case '/':
				while(!StackEmpty(Optr)){//栈不空循环 
					GetTop(Optr,e);//取栈顶元素 
					if(e=='*'||e=='/'){//将栈顶*或/运算符出栈并存放到postexp中 
						postexp[i++]=e;//将e存放到postexp中 
						Pop(Optr,e);//出栈元素e 
					}else{
						break;//e为非*或/运算符时退出循环 
					}
				}
				Push(Optr,*exp) ;//将*或/进栈
				exp++;//继续扫描其他字符 
				break; 
			default://处理数字字符 
				while(*exp>='0'&&*exp<='9'){//判定为数字字符 
					postexp[i++]=*exp;
					exp++;
				}
				postexp[i++]='#';//用#标识一个数字串 结束 
		}
	}
	while(!StackEmpty(Optr)){//此时exp扫描完毕,栈不空时循环 
		Pop(Optr,e);//出栈元素e 
		postexp[i++]=e;//将e存放到postexp中 
	}
	postexp[i]='\0';//给postexp表达式添加结束标识 
	DestroyStack(Optr);//销毁栈 
}

//字符型 
void InitStack(SqStack *&s);//初始化栈,构造一个空栈s
void DestroyStack(SqStack *&s) ;//销毁栈,释放栈s占用的存储空间
bool StackEmpty(SqStack *s) ;//判断栈是否为空,若栈为空,则返回真;否则返回假
bool Push(SqStack *&s,char e); //进栈,将元素e插入到栈s中作为栈顶元素
bool Pop(SqStack *&s,char &e);//出栈,从栈s中删除栈顶元素,并将其值赋给e
bool GetTop(SqStack *s,char &e);//取栈顶元素,返回当前栈顶元素,并将其值赋给e 

//double型 
void InitStack1(SqStack1 *&s);//初始化栈,构造一个空栈s
void DestroyStack1(SqStack1 *&s) ;//销毁栈,释放栈s占用的存储空间
bool StackEmpty1(SqStack1 *s) ;//判断栈是否为空,若栈为空,则返回真;否则返回假
bool Push1(SqStack *&s,double e); //进栈,将元素e插入到栈s中作为栈顶元素
bool Pop1(SqStack *&s,double &e);//出栈,从栈s中删除栈顶元素,并将其值赋给e
bool GetTop1(SqStack *s,double &e);//取栈顶元素,返回当前栈顶元素,并将其值赋给e 
//算术计算 
void trans(char *exp,char postexp[]);//将数组exp转化为转化为后缀表达式 postexp 
double compvalue(char * postexp);//后缀表达式计算
int main() {
	char exp1[]="1+2+3+4";
	char exp2[]="88-1*5";
	char exp3[]="1024/4*8";
	char exp4[]="(20+2)*(6/2)";
	char exp5[]="3-3-3";
	char exp6[]="8/(9-9)";
	char exp7[]="2*(6+2*(3+6*(6+6)))";
	char exp8[]="(((6+6)*6+3)*2+6)*2";
	char postexp1[MaxSize],postexp2[MaxSize],postexp3[MaxSize],postexp4[MaxSize],postexp5[MaxSize],postexp6[MaxSize],postexp7[MaxSize],postexp8[MaxSize];
	trans(exp1,postexp1);
	printf("1+2+3+4=%g\n",compvalue(postexp1));
	trans(exp2,postexp2);
	printf("88-1*5=%g\n",compvalue(postexp2));
	trans(exp3,postexp3);
	printf("1024/4*8=%g\n",compvalue(postexp3));
	trans(exp4,postexp4);
	printf("(20+2)*(6/2)=%g\n",compvalue(postexp4));
	trans(exp5,postexp5);
	printf("3-3-3=%g\n",compvalue(postexp5));
	trans(exp6,postexp6);
	printf("8/(9-9)=%g\n",compvalue(postexp6));
	trans(exp7,postexp7);
	printf("2*(6+2*(3+6*(6+6)))=%g\n",compvalue(postexp7));
	trans(exp8,postexp8);
	printf("(((6+6)*6+3)*2+6)*2=%g\n",compvalue(postexp8));
}

7. 栈与队列应用(II)----迷宫问题

( 1 )问题描述:以一个 m×n 的长方阵表示迷宫,0 和 1 分别表示迷宫
中的通路和障碍。设计一个程序,对任意设定的迷宫,求出一条从入
口到出口的通路,或得到没有通路的结论。
( 2 )基本要求:首先实现一个以链表作存储结构的栈类型,然后编写一个求解迷宫的非递归程序。求得的通路以三元组(i,j,d)的形式输出,
其中:(i,j)指示迷宫中的一个坐标,d 表示走到下一坐标的方向。如:
对于下列数据的迷宫,输出的一条通路为:
(1,1,1),(1,2,2),(2,2,2),(3,2,3),(3,1,2)…
3、测试数据:迷宫的测试数据如下:左下角(1,1)为入口,右下角(8,9)
为出口。
0 0 1 0 0 0 1 0
0 0 1 0 0 0 1 0
0 0 0 0 1 1 0 1
0 1 1 1 0 0 1 0
0 0 0 1 0 0 0 0
0 1 0 0 0 1 0 1
0 1 1 1 1 0 0 1
1 1 0 0 0 1 0 1
1 1 0 0 0 0 0 0
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 100
int mg[11][10]={{1,1,1,1,1,1,1,1,1,1},
				{1,0,0,1,0,0,0,1,0,1},
				{1,0,0,1,0,0,0,1,0,1},
				{1,0,0,0,0,1,1,0,1,1},
				{1,0,1,1,1,0,0,1,0,1},
				{1,0,0,0,1,0,0,0,0,1},
				{1,0,1,0,0,0,1,0,1,1},
				{1,0,1,1,1,1,0,0,1,1},
				{1,1,1,0,0,0,1,0,1,1},
				{1,1,1,0,0,0,0,0,0,1},
				{1,1,1,1,1,1,1,1,1,1}};
typedef struct{
	int i;
	int j;
	int di;
}Box;
typedef Box ElemType;
typedef struct linknode
{
	ElemType data;//数据域 
	struct linknode * next;//指针域 
 } LinkStNode;//链栈节点类型 

void InitStack(LinkStNode *&s){
 	s=(LinkStNode *)malloc(sizeof(LinkStNode));//分配地址 
 	s->next=NULL; 
 } 
void DestroyStack(LinkStNode *&s){
 	LinkStNode *pre=s,*p=s->next;//pre指向头结点,p指向首结点
	while(p!=NULL){//循到p为空 
		free(pre);//释放pre结点 
		pre=p;//pre,p同步后移 
		p=pre->next;
	} 
	free(pre);//此时pre指向尾结点,释放其空间 
 }
bool StackEmpty(LinkStNode *s){
 	return (s->next==NULL);
 } 
void Push(LinkStNode *&s,ElemType e){
 	LinkStNode *p;
 	p=(LinkStNode *)malloc(sizeof(LinkStNode));//新建结点p 
 	p->data=e;//存放元素e 
 	p->next=s->next;//j将p结点插入作为首结点 
 	s->next=p;
 }
bool Pop(LinkStNode *&s,ElemType &e){
 	LinkStNode *p;
 	if(s->next==NULL)//栈空的情况 
 		return false;//返回假 
 	p=s->next;//p指向首节点 
 	e=p->data;//提取首节点的值 
 	s->next=p->next;//删除首节点
	free(p);//释放被删除结点的存储空间
	return true;//返回2真 
 } 
bool GetTop(LinkStNode *s,ElemType &e){
 	if(s->next==NULL)//栈空的情况 
 		return false;//返回假 
 	e=s->next->data;//提取首节点值 
 	return true;//返回真 
 } 
void DispStack (LinkStNode *s ) {

	while (!StackEmpty(s) ) {
		ElemType e;
		Pop(s,e);
		printf ("%c", e);
	}
	printf("\n");
}
bool mgpath(int xi,int yi,int xe,int ye) {//求解路径为(xi,yi)->(xe,ye) 
	Box path[MaxSize],e;
	int i,j,di,i1,j1,k;
	bool find;
	LinkStNode *st;//定义栈 
	InitStack(st);//初始化栈 
	e.i=xi;e.j=yi;e.di=-1;//设置e为入口 
	Push(st,e);//方块e进栈 
	mg[xi][yi]=-1;//将入口的迷宫值置为-1,避免重复走到该方块 
	while (!StackEmpty(st)){//栈不空时循环 
		GetTop(st,e);//取栈顶方块e 
		i=e.i;j=e.j;di=e.di;
		if(i==xe&&j==ye){//找到了出口,输出该路径 
			printf("一条迷宫路径如下:\n");
			k=0;
			while(!StackEmpty(st)){
				Pop(st,e);//出栈方块e 
				path[k++]=e;//将e添加到path数组中 
			}
			while(k>=1){
				k--;
				printf("\t(%d,%d,%d)",path[k].i,path[k].j,path[k].di);
				if((k)%5==0) {printf("\n");}//每输出五个方块后换一行 
			}
			printf("\n");
			DestroyStack(st);//销毁栈 
			return true;//输出一条迷宫路径后返回true 
		}
		find=false;
		while (di<4 && !find){//找方块(i,j)的下一个相邻可走方块(i1,j1) 
			di++;
			switch(di){
				case 0:i1=i-1;j1=i;break;
				case 1:i1=i;j1=j+1;break;
				case 2:i1=i+1;j1=j;break;
				case 3:i1=i;j1=j-1;break;
			}
			if(mg[i1][j1]==0) find=true;//找到一个相邻可走方块,设置find为真 
		}
		if (find){//找到一个相邻可走方块(i1,j1) 
			st->next->data.di=di;//修改原栈顶元素的di值 
			e.i=i1;e.j=j1;e.di=-1;
			Push(st,e);//相邻可走方块e进栈 
			mg[i1][j1]=-1;//将(i1,j1)迷宫值置为-1,避免重复走到该方块 
			}
		else{//没有路径可走,则退栈 
			Pop(st,e);//将栈顶方块退栈 
			mg[e.i][e.j]=0;//让退栈方块的位置变为其他路径可走方块 
		}
	}
	DestroyStack(st);//销毁栈 
	return false;//表示没有可走路径,返回false 
}
 void DispStack (LinkStNode *s );	//遍历打印链表  
 void InitStack(LinkStNode *&s);//初始化栈,构造一个空栈 
 void DestroyStack(LinkStNode *&s);//销毁栈,释放栈s占用的存储空间 
 bool StackEmpty(LinkStNode *s);//判断栈是否为空,若栈s为空,则返回真;否者返回假 
 void Push(LinkStNode *&s,ElemType e);//进栈,将元素e插入到栈s中作为栈顶元素 
 bool Pop(LinkStNode *&s,ElemType &e);//出栈,从栈s中删除栈顶元素,并将其值赋给e 
 bool GetTop(LinkStNode *s,ElemType &e);//取栈顶元素,返回当前的栈顶元素,并将其赋值给e
 bool mgpath(int xi,int yi,int xe,int ye);//求解迷宫从(xi,yi)到出口(xe,ye)一条迷宫路径,路径存在则输出路径[(i,j,d),(i,J)表示迷宫坐标,d表示下一个坐标的方向],路径不存在则返回0 
 int main(){
 	if(mgpath(1,1,8,9)){
 		mgpath(1,1,8,9); 
 	}else{
 		printf("该迷宫问题没有解");
	 }
 }

 

8. 实现串的各种基本运算

编写一个程序 algo4-1.cpp,实现顺序串的各种基本运算,并在此基础上
设计一个程序 exp4-1.cpp 完成如下功能:
( 1 ) 建立串 s = “abcdefghefghijklmn”和串 s1 = “xyz”;
( 2 ) 输出串 s;
( 3 ) 输出串 s 的长度;
( 4 ) 在串 s 的第 9 个字符位置插入串 s1 而产生串 s2;
( 5 ) 输出串 s2;
( 6 ) 删除串 s 第 2 个字符开始的 5 个字符而产生串 s2;
( 7 ) 输出串 s2;
#include <stdio.h>
#include <malloc.h>
#define MaxSize 50
typedef struct{
	char data[MaxSize];//存放串字符 
	int length;//存放串长 
}SqString;//顺序串类型 
//生成串 
void StrAssign(SqString &s,char cstr[]){//s为引用参数 
	int i;
	for (i=0;cstr[i]!='\0';i++){
		s.data[i]=cstr[i];
	}
	s.length=i;//设置串的长度 
}
//输出串
void DispStr(SqString s){
	int i;
	if(s.length>0){
		for(i=0;i<s.length;i++){//遍历输出串中所有元素 
			printf("%c",s.data[i]);
		}
		printf("\n");
	}
}
//求串长
int StrLength(SqString s) {
	return s.length;
}
//子串的插入
SqString InsStr(SqString s1,int i,SqString s2) {
	int j;
	SqString str;//定义结果串 
	str.length=0;//设置str为空串 
	if (i<=0||i>s1.length+1){return str;}//参数不正常时返回空串
	for (j=0;j<i-1;j++) {//将s1.data[0,i-2]复制到str 
		str.data[j]=s1.data[j];
	}
	for (j=0;j<s2.length;j++){//将s2.data[0,s2.length-1]复制到str 
		str.data[i+j-1]=s2.data[j];
	}
	for (j=i-1;j<s1.length;j++){//将s1.data[i-1,s1.length-1]复制到str 
		str.data[s2.length+j]=s1.data[j];
	}
	str.length=s1.length+s2.length;
	return str;
}
//子串的删除
 SqString DelStr(SqString s,int i,int j) {
 	int k;
 	SqString str;//定义结果串 
 	str.length=0;//设置str为空串 
 	if(i<=0||i>s.length||i+j-1>s.length){return str;}//参数错误返回空串 
 	for(k=0;k<i-1;k++){//将s.data[0,i-1]复制到str 
 		str.data[k]=s.data[k];
	 }
	for(k=i+j-1;k<s.length;k++){//将s.data[i+j-1,s.length-1]复制到str 
		str.data[k-j]=s.data[k];
	}
	str.length=s.length-j;
	return str;
 }
 void StrAssign(SqString &s,char cstr[]);//将字符串常量cstr赋给串s,即生成其值等于cstr的串s 
 void DispStr(SqString s);//串输出,输出串s的所有字符值 
 int StrLength(SqString s);//求串长,返回串s中的字符个数 
 SqString InsStr(SqString s1,int i,SqString s2);//子串插入,将s2插入到串s1的第i(1<=i<=n+1)个位置,并返回产生的新串 
 SqString DelStr(SqString s,int i,int j);//子串删除,将串s2中删去从第i(1<=i<=n)个字符开始的长度为j的子串,并返回产生的新串 
 int main(){
 	SqString s;
	SqString s1;
	SqString s2;
 	char str0[] ="abcdefghefghijklmn";
 	char str1[]="xyz";
 	//(1)建立串s="abcdefghefghijklmn"和串s1="xyz" 
 	StrAssign(s,str0);
 	StrAssign(s1,str1);
 	//(2)输出串s 
 	printf("串s:");
 	DispStr(s);
 	//(3)输出串s的长度 
 	printf("串s的长度:");
 	printf("%d\n",StrLength(s));
 	//printf("%d",s.length); 
 	//(4)在串s的第九个字符位置插入串s1而产生串s2 
 	s2=InsStr(s,9,s1);
 	//(5)输出串s2; 
 	printf("插入操作后的新串s2:");
 	DispStr(s2);
 	//(6)删除串s第2个字符位置开始的5个字符而产生串s2 
 	s2=DelStr(s,2,5);
 	//(7)输出串s2 
 	printf("删除操作后的新串s2:"); 
 	DispStr(s2);
 }

由于我的实验让其12选8,我只选取前八大道来做,后面四道随缘更吧 

 9. 对称矩阵的和与乘积运算

10. 树及其应用(I)-----二叉树的遍历

11. 树及其应用(II)----哈夫曼编码
 
12. 图及其应用-----图的遍历
 
 

 

 

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值