开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第28天,点击查看活动详情.
- 目标:①、掌握线性表的表示和实现 ②、学会定义抽象数据类型 ③、学会分析问题,设计适当的解决方案 ④、深入掌握栈和队列应用的算法设计。
- **内容:**古代某法官要判决n个犯人的死刑,他有一条荒唐的法律,将犯人站成一个圆圈,从第s个人开始数起,每数到第d个犯人,就来出来处决,然后再从下一个开始数d个,数到的人再处决,……,直到剩下最后一个犯人予以赦免。
程序流程图:
**
- 问题概述: ----采用顺序存储和链式存储分别实现线性表类。①、线性表的操作至少应包含:判断是否为空;返回线性表长度;返回指定序号的对象;设置指定序号对象的值,并返回原对象的值;在指定位置上插入对象;追加一个对象;删除指定位置上的对象,并返回被删除的对象;清空线性表。②、若使用链式存储的线性表类,其单链表结点类的构造方法应有:无参构造方法、有参数构造方法和两参数构造方法。③、约瑟夫生者死者游戏的程序实现,给出当犯人个数n、计数起始位置数s和计数间隔数d不同时的测试结果。
**
- 源程序及系统文件使用说明
**
#include "stdafx.h"
#include <stdlib.h>
#include <iostream>
#define MaxSize 50
using namespace std;
typedef int ElemType;
typedef struct
{
ElemType data[MaxSize];
int length;
}
SqList; //顺序表类型
typedef struct LNode
{
ElemType data;
struct LNode * next;
}LinkNode;//单链表类型
void InitList(SqList *&L) //初始化线性表
{
L=(SqList *)malloc(sizeof(SqList));
L->length=0;
}
void DestroyList(SqList *&L) //销毁线性表
{
free(L);
}
bool ListEmpty(SqList *L) //判断线性表是否为空表
{
return(L->length==0);
}
int ListLength(SqList *L) //求线性长度
{
return(L->length);
}
void DispList(SqList *L)//输出线性表
{
for(int i=0;i<L->length;i++)
cout<<L->data[i]<<" ";
cout<<endl;
}
bool GetElem(SqList *L,int i,ElemType &e) //求线性表中某个数据元素值
{
if(i<1 || i>L->length)
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++;
if(i>=L->length)
return 0;
else
return i+1;
}
bool ListChange(SqList *&L,int i,ElemType e1,ElemType &e2) //修改数据元素
{
if(i<1 || i>L->length)
return false;
e2=L->data[i-1];
L->data[i-1]=e1;
return true;
}
bool ListInsert(SqList *&L,int i,ElemType e) //插入数据元素
{
int j;
if(i<1||i>L->length+1)
return false;
i--;
for(j=L->length;j>i;j--)
L->data[j]=L->data[j-1];
L->data[i]=e;
L->length++;
return true;
}
bool ListDelete(SqList *&L,int i,ElemType &e) //删除数据元素
{
int j;
if(i<1 || i>L->length)
return false;
i--;
e=L->data[i];
for(j=i;j<L->length-1;j++)
L->data[j]=L->data[j+1];
L->length--;
return true;
}
void ClearList(SqList*L) //清空线性表
{
L->length=0; //将线性表的长度置为0
}
void YueSeFu(SqList *&L,int n,int s,int d) //顺序表实现约瑟夫
{
int i;
int x;
/*
SqList *L;
InitList(L);
for(i=1;i<=n;i++)
{
ListInsert(L,i,i);
}//创建线性表
*/
cout<<"犯人最开始的排序为:"<<endl;
DispList(L);
if(ListEmpty(L)==false)
{while(ListLength(L)>1)
{
s=((s-1)-1+d+ListLength(L))%ListLength(L)+1;//如果从0起始换成1起始的话一个麻烦点的方法把定义域从[1,a]平移到[0,a-1]上就行了。
if(ListDelete(L,s,x))
cout<<" 序号为 "<<x<<" 的犯人被处决。"<<endl;
}
GetElem(L,1,x);//获取最后被释放的犯人序号
cout<<" 序号为 "<<x<<" 的犯人被释放。"<<endl;
}
DestroyList(L);//销毁线性表
}
void InitList1(LinkNode * &L)//初始化线性表
{
L=(LinkNode *)malloc(sizeof(LinkNode));
L->next=NULL;
}
bool ClearList1(LinkNode *&L) //不删除L头结点
{ //初始条件:线性表L已存在。操作结果:将L重置为空表
LinkNode * p, * q;
p=L->next; // p指向第一个结点 //
while(p) //没到表尾
{
q=p->next;
free(p);
p=q;
}
L->next=NULL; /* 头结点指针域为空 */
return true;
}
void DestoryList1(LinkNode * &L)//销毁线性表
{
LinkNode * pre=L,*p=L->next;
while(p!=NULL)
{
free(pre);
pre=p;
p=pre->next;
}
free(pre);
}
bool ListEmpty1(LinkNode * L)//判断线性表是否为空表
{
return(L->next==NULL);
}
int ListLength1(LinkNode * L)//求线性表的长度
{
int n=0;
LinkNode *p=L;
while (p->next!=NULL)
{
n++;
p=p->next;
}
return (n);
}
void DispList1(LinkNode *L)//输出线性表
{
LinkNode *p=L->next;
while(p!=NULL)
{
cout<<p->data<<" ";
p=p->next;
}
cout<<endl;
}
bool GetElem1(LinkNode *L,int i,ElemType &e)//求线性表的某个数据元素的值
{
int j=0;
LinkNode *p=L;
if(i<=0)
return false;
while(j<i && p!=NULL)
{
j++;
p=p->next;
}
if(p==NULL)
return false;
else
{
e=p->data;
return true;
}
}
bool ListChange1(LinkNode *L,int i,ElemType e1,ElemType &e2){//修改元素值
int j=0;
LinkNode *p=L;
if(i<=0)
return false;
while(j<i && p!=NULL)
{
j++;
p=p->next;
}
if(p==NULL)
return false;
else
{
e2=p->data;
p->data=e1;
return true;
}
}
int LocateElem1(LinkNode *L,ElemType e)//按元素值查找
{
int i=1;
LinkNode *p=L->next;
while(p!=NULL && p->data!=e)
{
p=p->next;
i++;
}
if(p==NULL)
return 0;
else
return (i);
}
bool ListInsert1(LinkNode * &L,int i,ElemType e)//插入数据元素
{
int j=0;
LinkNode * p=L,* s;
if(i<=0)
return false;
while(j<i-1 && p!=NULL)
{
j++;
p=p->next;
}
if(p==NULL)
return false;
else
{
s=(LinkNode *)malloc(sizeof(LinkNode));
s->data=e;
s->next=p->next;
p->next=s;
return true;
}
}
bool ListDelete1(LinkNode *&L,int i,ElemType &e)//删除数据元素
{
int j=0;
LinkNode *p=L,*q;
if(i<=0)
return false;
while(j<i-1 && p!=NULL)
{
j++;
p=p->next;
}
if(p==NULL)
return false;
else
{
q=p->next;
if(q==NULL)
return false;
e=q->data;
p->next=q->next;
free(q);
return true;
}
}
void Create_L(LinkNode *&L,int n) //构造一个以L为头结点,长度为n的单链表,节点元素依次为1.2.3...n
{
InitList1(L);
for(int i=1;i<=n;i++) //每循环依次增加一个结点,并为结点元素赋值
{
ListInsert1(L,i,i);
}
}
void Create_L1(LinkNode * &L) //改造为以L为头结点单循环链表,
{
LinkNode * p,* q;
p=L;
while(p->next!=NULL)
{
p=p->next;
}
q=L;
L=L->next;
p->next=L;
free(q); //删除原先的头结点
L=p;//让L对应第一个数据
}
void DispList2(LinkNode *L,int n)//输出单循环链表
{
LinkNode *p=L->next;
int i=0;
while(i<n)
{
cout<<p->data<<" ";
p=p->next;
i++;
}
cout<<endl;
}
void YueSeFu1(LinkNode * &L,int s,int d) //用单链表实现约瑟夫,即测试2
{
LinkNode * p=L;int j=0;
while(p&&j<s){p=p->next;j++;} //找到开始报数的位置
LinkNode * q;
while(p->next!=p)
{
for(int i=1;i<=d-1;i++)
{q=p;p=p->next;}
cout<<" 序号为 "<<p->data<<" 的犯人被处决。"<<endl; //输出被处决的序号
q->next=p->next;
free(p); //删除结点,并释放被删除的结点空间
p=q->next;
}
cout<<" 序号为 "<<p->data<<" 的犯人被释放。"<<endl; //输出最后一个犯人的序号
free(p);
}
void Shunxucunchu() //顺序存储方式实现
{
int Menu1;
int a,b,c;
SqList *L1;
InitList(L1);
do {
cout << "************************************************************" << endl;
cout << "*** 1.判断是否为空 ***" << endl;
cout << "*** 2.返回线性表长度 ***" << endl;
cout << "*** 3.返回指定序号的对象 ***" << endl;
cout << "*** 4.修改指定序号对象的值 ***" << endl;
cout << "*** 5.在指定位置上插入对象 ***" << endl;
cout << "*** 6.删除指定对象 ***" << endl;
cout << "*** 7.输出线性表 ***" << endl;
cout << "*** 8.清空线性表 ***" << endl;
cout << "*** 9.测试 ***" << endl;
cout << "*** 0.退出 ***" << endl;
cout << "************************************************************" << endl;
cout << "请输入您的选择:";
cin >> Menu1;
switch (Menu1)
{
case 1:
system("cls");
if(ListEmpty(L1))
cout<<endl<<"此表为空!"<<endl<<endl;
else
cout<<endl<<"此表不为空!"<<endl<<endl;
break;
case 2:
system("cls");
cout<<endl<<"线性表的长度为:"<<ListLength(L1)<<endl<<endl;
break;
case 3:
system("cls");
cout<<"请输入指定的序号: ";
cin>>a;
if(GetElem(L1,a,b))//求线性表中某个数据元素值
cout<<endl<<"第"<<a<<"号的值为 "<<b<<endl<<endl;
else
cout<<endl<<"查无此值!"<<endl<<endl;
break;
case 4:
system("cls");
cout<<endl<<"请输入要修改的序号和修改的值: ";
cin>>a>>b;
if(ListChange(L1,a,b,c))
cout<<endl<<"修改成功,修改前的值为 "<<c<<" ,修改后的值为 "<<b<<endl<<endl;
else
cout<<endl<<"修改失败!"<<endl<<endl;
break;
case 5:
system("cls");
cout<<endl<<"请输入要插入的序号和插入的值: ";
cin>>a>>b;
if(ListInsert(L1,a,b))
cout<<endl<<"插入成功!"<<endl<<endl;
else
cout<<endl<<"插入失败!"<<endl<<endl;
break;
case 6:
system("cls");
cout<<endl<<"请输入要删除的序号: ";
cin>>a;
if(ListDelete(L1,a,b))
cout<<endl<<"删除成功! 删除的值为 "<<b<<endl<<endl;
else
cout<<endl<<"删除失败!"<<endl<<endl;
break;
case 7:
system("cls");
cout<<endl<<"输出的线性表是:"<<endl;
DispList(L1);
cout<<endl;
break;
case 8:
system("cls");
ClearList(L1);
cout<<endl<<"线性表已清空!"<<endl;
break;
case 9:
system("cls");
int n; //定义犯人个数n
int s; //定义计数起始位置s
int d; //定义计数间隔数d
cout<<"请输入犯人个数n、计数起始位置数s和计数间隔数d:"<<endl;
cin>>n>>s>>d;
YueSeFu(L1,n,s,d); //用顺序表实现约瑟夫
break;
}
} while (Menu1!=0);
}
void LianShiCuncChu()//链式存储实现
{
int Menu2;
int a,b,c;
LinkNode *L2;
InitList1(L2);
do {
cout << "************************************************************" << endl;
cout << "*** 1.判断是否为空 ***" << endl;
cout << "*** 2.返回线性表长度 ***" << endl;
cout << "*** 3.返回指定序号的对象 ***" << endl;
cout << "*** 4.修改指定序号对象的值 ***" << endl;
cout << "*** 5.在指定位置上插入对象 ***" << endl;
cout << "*** 6.删除指定对象 ***" << endl;
cout << "*** 7.输出线性表 ***" << endl;
cout << "*** 8.清空线性表 ***" << endl;
cout << "*** 9.测试 ***" << endl;
cout << "*** 0.退出 ***" << endl;
cout << "************************************************************" << endl;
cout << "请输入您的选择:";
cin >> Menu2;
switch (Menu2)
{
case 1:
system("cls");
if(ListEmpty1(L2))
cout<<endl<<"此表为空!"<<endl<<endl;
else
cout<<endl<<"此表不为空!"<<endl<<endl;
break;
case 2:
system("cls");
cout<<endl<<"线性表的长度为:"<<ListLength1(L2)<<endl<<endl;
break;
case 3:
system("cls");
cout<<"请输入指定的序号: ";
cin>>a;
if(GetElem1(L2,a,b))//求线性表中某个数据元素值
cout<<endl<<"第"<<a<<"号的值为 "<<b<<endl<<endl;
else
cout<<endl<<"查无此值!"<<endl<<endl;
break;
case 4:
system("cls");
cout<<endl<<"请输入要修改的序号和修改的值: ";
cin>>a>>b;
if(ListChange1(L2,a,b,c))
cout<<endl<<"修改成功,修改前的值为 "<<c<<" ,修改后的值为 "<<b<<endl<<endl;
else
cout<<endl<<"修改失败!"<<endl<<endl;
break;
case 5:
system("cls");
cout<<endl<<"请输入要插入的序号和插入的值: ";
cin>>a>>b;
if(ListInsert1(L2,a,b))
cout<<endl<<"插入成功!"<<endl<<endl;
else
cout<<endl<<"插入失败!"<<endl<<endl;
break;
case 6:
system("cls");
cout<<endl<<"请输入要删除的序号: ";
cin>>a;
if(ListDelete1(L2,a,b))
cout<<endl<<"删除成功! 删除的值为 "<<b<<endl<<endl;
else
cout<<endl<<"删除失败!"<<endl<<endl;
break;
case 7:
system("cls");
cout<<endl<<"输出的线性表是:"<<endl;
DispList1(L2);
cout<<endl;
break;
case 8:
system("cls");
ClearList1(L2);
cout<<endl<<"线性表已清空!"<<endl;
break;
case 9:
system("cls");
int n; //定义犯人个数n
int s; //定义计数起始位置s
int d; //定义计数间隔数d
cout<<"请输入犯人个数n、计数起始位置数s和计数间隔数d:"<<endl;
cin>>n>>s>>d;
LinkNode *L;
Create_L(L,n); //创建循环单链表
cout<<"犯人最开始的排序为:"<<endl;
DispList1(L); //输出线性表
Create_L1(L);//改造为单循环链表
YueSeFu1(L,s,d); //用循环单链表实现约瑟夫
break;
}
} while (Menu2!=0);
}
int _tmain(int argc, _TCHAR* argv[])
{
int Menu;
do {
cout << "************************************************************" << endl;
cout << "******************欢迎来到约瑟夫生死游戏********************" << endl;
cout << "*** 1.使用顺序存储方法玩 ***" << endl;
cout << "*** 2.使用链式存储方法玩 ***" << endl;
cout << "*** 0.退出 ***" << endl;
cout << "************************************************************" << endl;
cout << "请输入您的选择:";
cin >> Menu;
switch (Menu)
{
case 1:
system("cls");
Shunxucunchu();//用顺序存储实现游戏
break;
case 2:
system("cls");
LianShiCuncChu();//用链式存储实现游戏
break;
}
} while (Menu!=0);
return 0;
}
- 开发环境与开发工具
**
-
开发环境:windows
-
开发工具:Microsoft Visual Studio 2010 选择依据:visual studio 2010是一个集成开发环境,利用它可以用C++、C#、VB、Java编程。
-
1、民主化的应用程序生命周期管理,坚持打造一个功能平等、共同分担的平台以用于组织内的应用程序生命周期管理过程。
-
2、符合新技术发展趋势;为开发者提供合适的工具和框架,以支持软件开发中最新的架构,开发和部署;
-
3、是新一代平台首选:微软投资于市场领先的操作系统,工具软件和服务器平台,为用户创造高效的解决方案。
-
4、高效的开发环境:Microsoft Visual Studio
2010采用拖拽式便能完成软件的开发。简单的操作便可以实现界面的生成,同时拖拽的界面,也有相应的代码来实现功能。可以快速实现相应的用户需求功能。