一.实验目的:
巩固线性表的数据结构的存储方法和相关操作,学会针对具体应用,使用线性表的相 关知识来解决具体问题。
二、实验内容:
1.建立一个由 n 个学生成绩的顺序表,n 的大小由自己确定,每一个学生的成绩信息由自己 确定,实现数据的对表进行插入、删除、查找等操作。分别输出结果。 要求如下: 1)用顺序表来实现。 2)用单链表来实现。 3)用双链表实现。 4)用静态链表实现。 5)用间接寻址实现。
1、用顺序表实现
#include<iostream>
using namespace std;
const int MaxSize=100;
class Seqlist
{
double score[MaxSize];
int length;
public:
Seqlist(){length=0;} //无参的构造函数,建立一个空的顺序表
Seqlist(double a[],int n) //有参的构造函数,建立一个长度为n的顺序表
{
if(n>MaxSize) throw"超过最大学生人数!";
for(int i=0;i<n;i++)
score[i]=a[i];
length=n;
}
~Seqlist(){} //析构函数
int Getlength(){return length;} //求线性表的长度
double Getnum(int i) //按位查找学生的成绩
{
if(i<1&&i>length) throw"不存在该学生!";
return score[i-1];
}
double Locate(double x) //按值查找学生的位置
{
if(x<0&&x>100) throw"分数非法!";
for(int i=0;i<length;i++)
if(score[i-1]==x)
return i;
return 0;
}
void Insert(int i,double x) //插入操作,在线性表的第i个位置插入值为x的学生会学生成绩
{
if(length>=MaxSize) throw"上溢";
if(i<1||i>length+1) throw"位置异常";
for(int j=length;j>=i;j--)
score[j]=score[j-1];
score[i-1]=x;
length++;
}
int Delete(int i) //删除操作,删除顺序表中的第i个位置的学生成绩
{
if(length==0) throw"下溢";
if(i<1||i>length) throw"位置异常";
double x;
x=score[i-1];
for(int j=i;j<length;j++)
score[j-1]=score[j];
length--;
return x;
}
void Print()
{
for(int i=0;i<length;i++)
cout<<"第"<<i+1<<"个学生的成绩为: "<<score[i]<<endl;
}
};
void main()
{
cout<<"***顺序表的代码与实现***"<<endl;
double a[5]={80,76,91.5,75,68.5};
Seqlist A(a,5);
cout<<"执行插入操作前的数据: "<<endl;
A.Print();
cout<<"执行插入操作,在第二个位置插入学生成绩85"<<endl;
A.Insert(2,85);
cout<<"执行插入操作后的数据: "<<endl;
A.Print();
cout<<"查询到第四个的位置上学生的成绩为: "<<A.Getnum(4)<<endl;
cout<<"查询学生成绩为75的位置为: "<<A.Locate(75)<<endl;
cout<<"执行删除操作,删除第二个的位置上学生的成绩"<<endl;
A.Delete(2);
cout<<"执行删除操作后的数据: "<<endl;
A.Print();
}
2、用单链表实现
#include<iostream>
using namespace std;
const int MaxSize=100;
template<class D> //定义模板类D
struct Node //定义结构体,用于结点的申请
{
D date;
Node<D> *next;
};
template<class D>
class Linklist
{
Node<D> *first; //单链表的头指针
public:
Linklist() //无参的构造函数,建立一个空的顺序表
{
first=new Node; //生成头结点
first->next=NULL; //头结点的指针域置为空
}
Linklist(D a[],int n) //有参的构造函数,建立一个长度为n的顺序表
{
Node<D> *r,*s;
first=new Node<D>; //生成头结点
r=first; //尾指针初始化
for(int i=0;i<n;i++)
{
s=new Node<D>;s->date=a[i]; //为每一个数组元素建立一个结点
r->next=s;r=s; //将结点s插入到头结点之后
}
r->next=NULL; //将终端结点的指针置为空
}
~Linklist() //析构函数
{
Node<D> *q=NULL;
while(first!=NULL) //释放单链表的每一个结点的存储空间
{
q=first; //暂存被释放结点
first=first->next; //first指向被释放结点的下一个结点
delete q;
}
}
int Length() //求线性表的长度
{
Node<D> *p=NULL;
p=first->next;count=0; //工作指针p和累加器count初始化
while(p!=NULL)
{
p=->next;
count++;
}
return count;
}
double Getnum(int i) //按位查找学生的成绩
{
Node<D> *p=NULL;
p=first->next;int count=1; //工作指针p和累加器count初始化
while(p!=NULL&&count<i)
{
p=p->next; //工作指针p后移
count++;
}
if(p==NULL) throw"位置异常";
return p->date;
}
double Locate(double x) //按值查找学生的位置
{
Node<D> *p=NULL;
p=first->next;int count=1; //工作指针p和累加器count初始化
while(p!=NULL)
{
if(p->date==x) return count; //查找成功,结束函数并返回序号
p=p->next;
count++;
}
cout<<"查找失败"<<endl;
return 0; //退出循环表明查找失败
}
void Insert(int i,double x) //插入操作,在线性表的第i个位置插入值为x的学生会学生成绩
{
Node<D> *p=NULL,*s;
p=first;int count=0; //工作区间p应指向头结点
while(p!=NULL&&count<i-1) //查找第i-1个结点
{
p=p->next; //工作指针后移
count++;
}
if(p==NULL) throw"位置异常,找不到结点";
else
{
s=new Node<D>;s->date=x; //申请一个结点s,其数据域为x
s->next=p->next;p->next=s; //将结点s插入到结点p之后
}
}
int Delete(int i) //删除操作,删除顺序表中的第i个位置的学生成绩
{
Node<D> *p=NULL,*q=NULL;
int x;
p=first;int count=0; //工作区间p应指向头结点
while(p!=NULL&&count<i-1) //查找第i-1个结点
{
p=p->next; //工作指针后移
count++;
}
if(p==NULL||p->next==NULL) throw"位置异常"; //结点p不存在或者p的后继结点不存在
else
{
q=p->next;x=q->date; //暂存被删结点
p->next=q->next; //摘链
delete q;
return x;
}
}
void Print()
{
Node<D> *p=NULL;
p=first->next; //工作指针初始化
while(p!=NULL)
{
cout<<p->date<<" ";
p=p->next; //工作指针后移
}
cout<<endl;
}
};
void main()
{
cout<<"***单链表的代码与实现***"<<endl;
int a[5]={80,76,91,75,68.5};
Linklist <int>A(a,5);
cout<<"执行插入操作前的数据: "<<endl;
A.Print();
cout<<"执行插入操作,在第二个位置插入学生成绩85"<<endl;
A.Insert(2,85);
cout<<"执行插入操作后的数据: "<<endl;
A.Print();
cout<<"查询到第四个的位置上学生的成绩为: "<<A.Getnum(4)<<endl;
cout<<"查询学生成绩为75的位置为: "<<A.Locate(75)<<endl;
cout<<"执行删除操作,删除第二个的位置上学生的成绩"<<endl;
A.Delete(2);
cout<<"执行删除操作后的数据: "<<endl;
A.Print();
}
3、用双链表实现
#include<iostream>
using namespace std;
const int MaxSize=100;
template<class D> //定义模板类D
struct Node //定义结构体,用于结点的申请
{
D date;
Node<D> *prior,*next;
};
template<class D>
class Linklist
{
Node<D> *first; //单链表的头指针
public:
Linklist() //无参的构造函数,建立一个空的顺序表
{
first=new Node; //生成头结点
first->next=NULL; //头结点的指针域置为空
}
Linklist(D a[],int n) //有参的构造函数,建立一个长度为n的顺序表
{
Node<D> *r,*s;
first=new Node<D>; //生成头结点
r=first; //尾指针初始化
for(int i=0;i<n;i++)
{
s=new Node<D>;s->date=a[i]; //为每一个数组元素建立一个结点
r->next=s;r=s; //将结点s插入到头结点之后
}
r->next=NULL; //将终端结点的指针置为空
}
~Linklist() //析构函数
{
Node<D> *q=NULL;
while(first!=NULL) //释放单链表的每一个结点的存储空间
{
q=first; //暂存被释放结点
first=first->next; //first指向被释放结点的下一个结点
delete q;
}
}
int Length() //求线性表的长度
{
Node<D> *p=NULL;
p=first->next;count=0; //工作指针p和累加器count初始化
while(p!=NULL)
{
p=->next;
count++;
}
return count;
}
double Getnum(int i) //按位查找学生的成绩
{
Node<D> *p=NULL;
p=first->next;int count=1; //工作指针p和累加器count初始化
while(p!=NULL&&count<i)
{
p=p->next; //工作指针p后移
count++;
}
if(p==NULL) throw"位置异常";
return p->date;
}
double Locate(double x) //按值查找学生的位置
{
Node<D> *p=NULL;
p=first->next;int count=1; //工作指针p和累加器count初始化
while(p!=NULL)
{
if(p->date==x) return count; //查找成功,结束函数并返回序号
p=p->next;
count++;
}
cout<<"查找失败"<<endl;
return 0; //退出循环表明查找失败
}
void Insert(int i,D x) //插入操作,在线性表的第i个位置插入值为x的学生会学生成绩
{
Node<D> *p,*s;
p=first;int count=0; //工作区间p应指向头结点
while(p!=NULL&&count<i-1) //查找第i-1个结点
{
p=p->next; //工作指针后移
count++;
}
if(p==NULL) throw"位置异常,找不到结点";
else
{
s=new Node<D>;
s->date=x; //申请一个结点s,其数据域为x
s->prior=p;
s->next=p->next;
p->next->prior=s;
p->next=s; //将结点s插入到结点p之后
}
}
int Delete(int i) //删除操作,删除顺序表中的第i个位置的学生成绩
{
Node<D> *p=NULL,*q=NULL;
int x;
p=first;int count=0; //工作区间p应指向头结点
while(p!=NULL&&count<i-1) //查找第i-1个结点
{
p=p->next; //工作指针后移
count++;
}
if(p==NULL||p->next==NULL) throw"位置异常"; //结点p不存在或者p的后继结点不存在
else
{
q=p->next;x=q->date; //暂存被删结点
p->next=q->next; //摘链
(q->next)->prior=p->prior;
delete q;
return x;
}
}
void Print()
{
Node<D> *p=NULL;
p=first->next; //工作指针初始化
while(p!=NULL)
{
cout<<p->date<<" ";
p=p->next; //工作指针后移
}
cout<<endl;
}
};
void main()
{
cout<<"***双链表的代码与实现***"<<endl;
int a[5]={80,76,91,75,68.5};
Linklist <int>A(a,5);
cout<<"执行插入操作前的数据: "<<endl;
A.Print();
cout<<"执行插入操作,在第二个位置插入学生成绩85"<<endl;
A.Insert(2,85);
cout<<"执行插入操作后的数据: "<<endl;
A.Print();
cout<<"查询到第四个的位置上学生的成绩为: "<<A.Getnum(4)<<endl;
cout<<"查询学生成绩为75的位置为: "<<A.Locate(75)<<endl;
cout<<"执行删除操作,删除第二个的位置上学生的成绩"<<endl;
A.Delete(2);
cout<<"执行删除操作后的数据: "<<endl;
A.Print();
}
4、用静态链表实现
#include<iostream>
using namespace std;
const int MaxSize=100;
template<class D>
struct Node
{
D data;
int next;
};
template<class D>
class SL //定义静态链表的类
{
private:
int first;
int avail;
int length;
Node<D> list[MaxSize];
public:
SL(); //无参构造
SL(D a[],int n); //有参构造
~SL(){} //析构函数
int Length(); //静态链表的长度
D Get(int i); //按位查找
int Locate(D x); //按值查找
void Insert(int i,D x); //插入操作
D Delete(int i); //删除操作
void Print(); //遍历操作
};
template<class D>
SL<D>::SL()
{
first=0;
list[0].next=avail=1;
for(int i=1;i<MaxSize-1;i++)
list[i].next=i+1; //初始化空闲链
list[MaxSize-1].next=-1; //置空闲链结束的标志
}
template<class D>
SL<D>::SL(D a[],int n)
{
length=0;
int s;
if(n<=0||n>MaxSize) throw"error";
first=0;
list[0].next=avail=1;
for(int i=1;i<MaxSize-1;i++)
list[i].next=i+1; //初始化空闲链
list[MaxSize-1].next=-1; //置空闲链结束的标志
for(int j=0;j<n;j++)
{
s=avail;
list[s].data=a[j];
avail=list[avail].next;
length++;
}
list[s].next=-1;
}
template<class D>
int SL<D>::Length()
{
int p=list[first].next;count=0;
while(p!=-1)
{
p=list[p].next;
count++;
}
return count;
}
template<class D>
D SL<D>::Get(int i)
{
if(i<=0||i>length) throw"位置非法";
int p=list[first].next,count=1; //工作指针p和累加器count初始化
while(p!=-1&&count<i)
{
p=list[p].next; //工作指针后移
count++;
}
if(p==-1) throw"位置";
return list[p].data;
}
template<class D>
int SL<D>::Locate(D x)
{
int p=list[first].next,count=1;
while(p!=-1)
{
if(list[p].data==x) return count; //查找成功,结束函数并返回序号
p=list[p].next;
count++;
}
return 0; //退出循环表明查找失败
}
template<class D>
void SL<D>::Insert(int i,D x)
{
int p=list[first].next,count=0;
while(p!=-1&&count<i-1) //查找第i-1个结点
{
p=list[p].next;
count++;
}
if(p==-1) throw"位置";
int s=avail; //不用申请新结点,利用空闲链的第一个结点
avail=list[avail].next; //空闲链的头指针后移
list[s].data=x; //将x填入下标为s的结点
list[s].next=list[p].next; //将下标为s的结点插入到下标为p的结点后面
list[p].next=s;
}
template<class D>
D SL<D>::Delete(int i)
{
int p=list[first].next,count=0;
while(p!=-1&&count<i-1) //查找第i-1个结点
{
p=list[p].next;
count++;
}
if(p==-1||list[p].next==-1) throw"位置"; //结点p不存在或者p的后继结点不存在
int q=list[p].next; //暂存被删结点
list[p].next=list[q].next; //摘链
list[q].next=avail; //将结点q插入空闲链avail的最前端
avail=q; //空闲链头指针avail指向结点q
return list[p].data;
}
template<class D>
void SL<D>::Print()
{
int p=list[first].next, count=1; //工作指针p初始化
while(p!=-1)
{
cout<<"第"<<count<<"学生的成绩为: "<<list[p].data<<endl;
p=list[p].next; //工作指针p后移
count++;
}
}
void main()
{
cout<<"***静态链表的代码与实现。***"<<endl;
float a[5]={80,76,91.5,75,68.5};
SL<float> A(a,5);
cout<<"执行插入操作前的数据: "<<endl;
A.Print();
cout<<"执行插入操作,在第二个位置插入学生成绩85"<<endl;
A.Insert(2,85);
cout<<"执行插入操作后的数据: "<<endl;
A.Print();
cout<<"查询到第四个的位置上学生的成绩为: "<<A.Get(4)<<endl;
cout<<"查询学生成绩为75的位置为: "<<A.Locate(75)<<endl;
cout<<"执行删除操作,删除第二个的位置上学生的成绩"<<endl;
A.Delete(2);
cout<<"执行删除操作后的数据: "<<endl;
A.Print();
}
5、用间接寻址实现
#include<iostream>
using namespace std;
const int MaxSize=100;
template<class D> //定义模板类
struct Node
{
D data;
};
template<class D>
class Inadd //定义间接寻址类
{
public:
Inadd(){length=0;} //无参的构造函数
Inadd(D a[],int n); //带参的构造函数
~Inadd(){} //析构函数
int Length(){return length;} //求表的长度
D Get(int i); //按位查找
int Locate(D x); //按值查找
void Insert(D x,int i); //插入操作
D Delete(int i); //删除操作,按位删除
void Print(); //遍历操作
private:
Node<D> *add[MaxSize]; //创建存储指向该元素的指针的数组
int length; //表的长度
};
template<class D>
Inadd<D>::Inadd(D a[],int n)
{
if(n>MaxSize) throw"超过最大学生人数!";
for(int i=0;i<n;i++)
{
add[i]=new Node<D>;
add[i]->data=a[i];
}
length=n;
}
template<class D>
D Inadd<D>::Get(int i)
{
if(i<1||i>length) throw"参数非法";
return add[i-1]->data;
}
template<class D>
int Inadd<D>::Locate(D x)
{
for(int i=0;i<length;i++)
if(add[i]->data==x) return i+1;
return 0;
}
template<class D>
void Inadd<D>::Insert(D x,int i)
{
if(length>MaxSize) throw"上溢";
if(i<1||i>length+1) throw"参数非法";
for(int j=length;j>=i;j--)
add[j]=add[j-1];
add[i-1]->data=x;
length++;
}
template<class D>
D Inadd<D>::Delete(int i)
{
if(length==0) throw"下溢";
if(i<1||i>length) throw"参数非法";
int x=add[i-1]->data;
for(int j=i;j<length;j++)
add[j-1]->data=add[j]->data;
length--;
return x;
}
template<class D>
void Inadd<D>::Print()
{
for(int i=0;i<length;i++)
cout<<"第"<<i+1<<"个学生的成绩是: "<<add[i]->data<<endl;
}
void main()
{
cout<<"***间接寻址的代码与实现***"<<endl;
float a[5]={80,76,91.5,75,68.5};
Inadd<float> A(a,5);
cout<<"执行插入操作前的数据: "<<endl;
A.Print();
cout<<"执行插入操作,在第二个位置插入学生成绩85"<<endl;
A.Insert(85,2);
cout<<"执行插入操作后的数据: "<<endl;
A.Print();
cout<<"查询到第四个的位置上学生的成绩为: "<<A.Get(4)<<endl;
cout<<"查询学生成绩为75的位置为: "<<A.Locate(75)<<endl;
cout<<"执行删除操作,删除第二个的位置上学生的成绩"<<endl;
A.Delete(2);
cout<<"执行删除操作后的数据: "<<endl;
A.Print();
}