本文是自己数据结构与算法的实验作业,只为了便于自己查看和学习,有问题的地方还望斧正,所用软件为devc++,以下代码拿去都能直接运行。
目录
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. 图及其应用-----图的遍历