一、实验目的
1.熟悉C语言的上机环境,掌握使用VC环境上机调试程序的基本方法;
2.会定义线性表的顺序存储结构。
3.熟悉对顺序表的一些基本操作和具体的函数定义。
4.理解利用基本操作进行一些实际的应用型程序设计。
二、实验题目
1.基础题:请编程实现顺序表的各种基本操作,并通过简单应用测试各函数的正确性。
2.应用题:求集合 A、B 的并集 C。
三、设计部分
1.抽象数据类型定义为:
ADT List {
数据对象:D={ai|ai∈ElemSet, i=1,2,…,n,n≥0}
数据关系:R={<ai,ai+1>|ai,ai+1 ∈D, i=1,2,…,n-1,n≥1}
2.基本操作之间的调用关系:
void init(sqlist &L) //构造一个空的顺序表
bool empty(sqlist L) //判断是否为空表
int length (sqlist L) //求线性表长度
elemtype get(sqlist L, int i)
//在线性表L中求序号为i的元素,该元素作为函数返回值;
int locate(sqlist L,elemtype e)
//返回e元素在顺序表L中第一次出现的位序,若不存在,返回0
int insert (sqlist &L, int i , elemtype e)
//在线性表L中第i个数据元素之前插入新数据元素e;
int delet(sqlist &L,int i) //将线性表L中第i个数据元素删除;
void clear(sqlist &L) //清空线性表,不销毁
void printl(sqlist L) //遍历函数,顺序输出顺序表中的各元素的值
void MergeList(SqList &La,SqList &Lb)//线性表的合并
void BubbleSort(SqList &L)//冒泡排序;
3.结构体的定义:
struct list{
elemtype *elem;
int length;
};
typedef struct list sqlist;
四、算法实现
数据元素类型:
typedef int ElemType;typedef int Status;
#define OK 1
#define error 0
#define OVERFLOW -2
1. 按位查找操作
(1)算法步骤
①检测查找位置是否合法,若不合法则返回0。
②将顺序表中序号为i的元素值作为函数返回值。
(2)程序代码
elemType get(sqlist L, int i)//在线性表L中求序号为i的元素,该元素作为函数返回值;
{
if(i<1||i>L.length) return error;
int e=L.elem[i-1];
return e;
}
2. 按值查找操作
(1)算法步骤
①遍历顺序表查找e元素是否存在。
②若e元素存在,返回e元素的位序。
③若不存在则返回0。
(2)程序代码
int locate(sqlist L,int e)//返回e元素在顺序表L中第一次出现的位序,若不存在,返回0
{
int i;
for(i=0;i<L.length;i++){
if(L.elem[i]==e) return i+1;
}
return 0;
}
3. 插入操作
(1)算法步骤:
①判断插入位置 i 是否合法,若不合法,输出“插入位置出界”并返回 0;
②判断顺序表的存储空间是否已满,若满则输出“顺序表已经满了!”并返回 0;
③逆序将第 n 个到第 j个位置的元素依次向后移动一个位置,空出第 j个位置;
④将要插入的新元素 e 放在第 i 个位置;
⑤表长加 1;返回 1。
(2)程序代码
int insert (sqlist &L, int i , elemType e)
//在线性表L中第i个数据元素之前插入新数据元素e;
{
if (i<1||i>L.length+1)
{
printf("插入位置出界");
return error;
}
if(L.length==MAXSIZE){
printf("顺序表已经满了!");
return error;
}
int j;
for(j=L.length-1;j>=i-1;j--){
L.elem[j+1]=L.elem[j];
}
L.elem[i-1]=e;
++L.length;
return OK;
}
4. 删除操作
(1)算法步骤:
①判断删除位置是否合法,若不合法输出“删除位置出界”并返回0。
②将第i个到最后一个元素依次向前挪动一个位置。
③表长减一,返回1。
(2)程序代码
int delet(sqlist &L,int i) //将线性表L中第i个数据元素删除;
{
if (i<1||i>L.length){
printf("删除位置出界");
return error;}
for(int j=i;j<=L.length-1;j++){
L.elem[j-1]=L.elem[j];
}
--L.length;
return OK;
}
5. 顺序表的合并操作
(1) 算法步骤:
①将第二个顺序表的元素依次用后插法插入到第一个顺序表中。
(2) 程序代码:
void MergeList(SqList &La,SqList &Lb)
{
int m,n,e,i;
m=La.length;
n=Lb.length;
for(i=1;i<=n;i++)
{
get(Lb,i,e);
if(!locate(La,e,i))
insert(La,++m,e);
}
}
(3) 算法改进:可以用一个新的顺序表存入两个表的并集,这样可以避免第一个顺序表元素个数超出。
6.冒泡排序
(1) 算法步骤:
①重复扫描待排序序列,并比较每一对相邻的元素,当该对元素顺序不正确时进行交换。一直重复这个过程,直到没有任何两个相邻元素可以交换,就表明完成了排序。
(2) 程序代码:
void BubbleSort(SqList &L){ //冒泡排序;
int m,flag,j,t;
m=L.length-1;
flag=1;//用flag标记一趟排序是否发生交换;
while((m>0)&&(flag==1))
{
flag=0;
for(j=1;j<=m;j++)
{
if(L.elem[j]>L.elem[j+1])
{
flag=1;
t=L.elem[j];
L.elem[j]=L.elem[j+1];
L.elem[j+1]=t;
}
}
--m;
}
后附完整程序代码
1.基础题
#include <iostream>
#include <string>
using namespace std;
#define OK 1
#define error 0
#define OVERFLOW -2
typedef int Status;
typedef int elemType;
// 顺序表的存储结构
#define MAXSIZE 100
typedef struct list
{
elemType *elem;
int length;
}sqlist;
void init(sqlist &L) //构造一个空的顺序表
{
L.elem=new elemType[MAXSIZE];
if(!L.elem) exit(OVERFLOW);
L.length=0;
}
bool empty(sqlist L) //判断是否为空表
{
if(L.length==0) return true;
return false;
}
int length (sqlist L) //求线性表长度
{
return L.length;
}
elemType get(sqlist L, int i)
//在线性表L中求序号为i的元素,该元素作为函数返回值;
{
if(i<1||i>L.length) return error;
int e=L.elem[i-1];
return e;
}
int locate(sqlist L,int e)
//返回e元素在顺序表L中第一次出现的位序,若不存在,返回0
{
int i;
for(i=0;i<L.length;i++){
if(L.elem[i]==e) return i+1;
}
return 0;
}
int insert (sqlist &L, int i , elemType e)
//在线性表L中第i个数据元素之前插入新数据元素e;
{
if (i<1||i>L.length+1)
{
printf("插入位置出界");
return error;
}
if(L.length==MAXSIZE){
printf("顺序表已经满了!");
return error;
}
int j;
for(j=L.length-1;j>=i-1;j--){
L.elem[j+1]=L.elem[j];
}
L.elem[i-1]=e;
++L.length;
return OK;
}
int delet(sqlist &L,int i) //将线性表L中第i个数据元素删除;
{
if (i<1||i>L.length){
printf("删除位置出界");
return error;}
for(int j=i;j<=L.length-1;j++){
L.elem[j-1]=L.elem[j];
}
--L.length;
return OK;
}
void clear(sqlist &L) //清空线性表,不销毁
{
L.length=0;
}
void printl(sqlist L) //遍历函数,顺序输出顺序表中的各元素的值
{
int i=0;
while (i!=L.length)
{
cout << L.elem[i];
printf(" ");
i++;
}
}
void destroy(sqlist &L){
if(L.elem) delete[]L.elem;
L.elem=NULL;
L.length=0;
}
int main()
{
sqlist mylist; //定义结构体变量
elemType x; //数据元素类型的变量
int i=1; //辅助变量,主要用于表示位序
init(mylist); //测初始化函数
if(empty(mylist)) //测试判空函数
cout<<"初始化为空表"<<endl;
cout<<"输入int,创建顺序表,以-1结束:"<<endl;
cin>>x;
while ( x!= -1 )
{
if (insert(mylist,i,x)==0) { //通过反复插入,创建表
cout<<"错误!"<<endl;
return error;
}
i++;
cin>>x;
}
printl(mylist);
printf("\n"); //测试输出函数
cout<<"表长为:"<<length(mylist)<<endl; //测求长度函数
cout<<"删除第几个?";
cin>>i;
delet(mylist,i); //测删除函数
printl(mylist);
printf("\n");
cout<<"第几个位置插入?";
cin>>i;
cout<<"插入的元素为?";
cin>>x;
insert(mylist,i,x); //测插入函数
printl(mylist);
printf("\n");
cout<<"读取第几个?";
cin>>i;
cout<<get(mylist,i)<<endl; //测读取操作
cout<<"查找什么元素\n";
cin>>x;
i=locate(mylist,x); //测查找操作
if(i!=0) cout<<"位序为"<<i<<endl;
else cout<<"不存在"<<endl;
clear(mylist); //测清空函数
cout<<"清空后,表长为:"<<length(mylist)<<endl;
destroy(mylist);*/
}
2.应用题
#include <iostream>
#include <string>
using namespace std;
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;
typedef int ElemType;
#define LIST_INIT_SIZE 100
// 顺序表的存储结构
#define MAXSIZE 100
typedef struct SqList
{
ElemType *elem;
int length;
}SqList;
//基础变化
Status get(SqList L, int i,ElemType &e)
{
if(i<1||i>L.length)return ERROR;
e=L.elem[i-1];
return 1;
}
int locate(SqList L, int e,int i)
{
for(i=0;i<L.length;i++)
if(L.elem[i]==e)return i+1;
return 0;
}
int length (SqList L){
return L.length;}
Status insert(SqList &L, int i, ElemType e)
{
if ( i < 1 || i > L.length + 1) {
cout<<"Insert at "<<i<<" 出界了!"<<endl;
return ERROR;
}
if ( L.length == MAXSIZE ) {
cout<<"顺序表满了!"<<endl;
return ERROR;
}
for ( int j = L.length-1; j >= i-1; j-- )
L.elem[j+1] = L.elem[j];
L.elem[i-1]=e;
++L.length;
cout<<"Insert at "<<i<<" OK!"<<endl;
return OK;
}
//定义空表
void init(SqList &L)
{
L.elem = new ElemType[MAXSIZE];
if (!L.elem) exit(OVERFLOW);
L.length =0;
}
//输出集合元素
void PrintList(SqList L)
{
printf("当前顺序表所有元素:");
for (int i = 0; i<L.length; i++)
{
printf("%d ", L.elem[i]);
}
printf("\n");
}
// 初始化集合前n项元素
int CreatList(SqList &L, int n)
{
if (n < 0 || n > LIST_INIT_SIZE)
return ERROR; //n非法
for (int i = 0; i<n; i++)
{
scanf("%d", &L.elem[i]);
L.length++;
}
return OK;
}
//输入元素
void Create(SqList &L)
{
int n;
L.length = 0;
printf("请输入要创建的顺序表长度(>1):");
scanf("%d", &n);
printf("请输入%d个数(用空格隔开): ", n);
if ( CreatList(L, n) )
{
printf("创建成功!\n");
PrintList(L);
}
else
printf("输入长度非法!\n");
}
// 线性表的合并
void MergeList(SqList &La,SqList &Lb)
{
int m,n,e,i;
m=La.length;
n=Lb.length;
for(i=1;i<=n;i++)
{
get(Lb,i,e);
if(!locate(La,e,i))
insert(La,++m,e);
}
}
void BubbleSort(SqList &L){ //冒泡排序;
int m,flag,j,t;
m=L.length-1;
flag=1;//用flag标记一趟排序是否发生交换;
while((m>0)&&(flag==1))
{
flag=0;
for(j=1;j<=m;j++)
{
if(L.elem[j]>L.elem[j+1])
{
flag=1;
t=L.elem[j];
L.elem[j]=L.elem[j+1];
L.elem[j+1]=t;
}
}
--m;
}
}
int main()
{
SqList La;
init(La);
Create(La);
SqList Lb;
init(Lb);
Create(Lb);
MergeList(La,Lb);
PrintList(La);
}