一、线性表的定义:
(1)概念定义:用数据元素的有限序列表示叫做线性表;线性表中数据元素的类型可以为简单类型,也可以为复杂类型。许多实际应用问题所涉的基本操作有很大相似性,不应为每个具体应用单独编写一个程序。从具体应用中抽象出共性的逻辑结构和基本操作(抽象数据类型),然后实现其存储结构和基本操作。
(2)类型定义:首先抽象出ADT List表的结构,在C/C++中一般都是采用struct来实现的。基本操作有如下:InitList(&L):创建一个新表;DestroyList(&L):销毁一个线性表;ClearList(&L):清空表;ListEmpty(L):判断表是否为空;ListLength(L):求表的长度;GetElem(L,i,&e):读取表的元素;LocateElem(L,e):查找表的元素; PriorElem(L,cur_ e,&pre _e):求表的前驱;NextElem(L,cur_ e,&next_e) :求表的后继;ListInsert(&L,i,e) :前插表;ListDelete(&L,i,&e):删除表;TraverseList (L):遍历表;
二、线性表的顺序表示和实现
(1)概念:线性表的顺序表示又称为顺序存储结构或顺序映像。顺序存储定义:把逻辑上相邻的数据元素存储在物理上相邻的存储单元中的存储结构。逻辑上相邻,物理上也相邻;用一组地址连续的存储单元依次存储线性表的元素,可通过数组V[n]来实现。
(2)实现:下面是具体代码的大概实现;
using namespace std;
typedef int ElemType;
typedef int Status;
typedef struct{
ElemType *elem;
int length;
}SqList;
Status InitList_Sq(SqList &L){//创建一个空的顺序表L
L.elem = new ElemType[MAXSIZE];
if(!L.elem)
exit(OVERFLOW);
L.length = 0;
return OK;
}
void DestoryList_Sq(SqList &L){//销毁线性表L
if(L.elem)
delete[]L.elem;//释放存储空间
}
void ClearList_Sq(SqList &L){//清空线性表L
L.length = 0;
}
int GetLength_Sq(SqList &L){//求线性表L的长度
return (L.length);
}
int IsEmpty_Sq(SqList L){//判断线性表为空
if(L.length == 0)
return 1;
else
return 0;
}
Status GetElem_Sq(SqList L,int i,ElemType &e){//获取元素
if(i<1 || i>L.length) //判断i值是否合理,若不合理,返回ERROR
return ERROR;
e = L.elem[i-1]; ////第i-1的单元存储着第i个数据
return OK;
}
int LocateElem_Sq(SqList L,ElemType e){//查找元素
for(int i=0; i<L.length; i++){
if(L.elem[i] == e)
return i+1; //查找的元素实际上是在第i+1个位置
}
return 0;
}
Status InsertElem_Sq(SqList &L,int i,ElemType e){
if(i<1 || i>L.length+1)
return ERROR; //插入位置的i值不合法
if(L.length == MAXSIZE)
return ERROR; //当前的存储空间已满
for(int j=L.length-1; j>=i-1; j--){
L.elem[j+1] = L.elem[j]; //插入位置及之后的元素后移
}
L.elem[i-1] = e; //将新元素e放入第i个位置
++L.length; //表长增加1
return OK;
}
Status DeleteElem_Sq(SqList &L,int i){
if(i<1 || i>L.length)
return ERROR; //删除位置不合法
for(int j=i;j<=L.length-1;j++){
L.elem[j-1] = L.elem[j]; //被删除元素之后的元素前移
}
--L.length; //表长减少1
return OK;
}
void print(SqList L){
for(int i=0;i<L.length;i++){
cout<<L.elem[i]<<endl;
}
}
int main(){
SqList lst;
InitList_Sq(lst);
int i,n;
ElemType e;
cout<<"请输入顺序表的长度:"<<endl;
cin>>n;
for(i=1;i<=n;i++){
cout<<"请输入第"<<i<<"个元素:"<<endl;
cin>>e;
InsertElem_Sq(lst,i,e);
}
print(lst);
cout<<"请问要删除第几个元素:"<<endl;
cin>>i;
DeleteElem_Sq(lst,i);
print(lst);
cout<<"要在第几个位置插入元素?"<<endl;
cin>>i;
cout<<"需要插入的元素是?"<<endl;
cin>>e;
InsertElem_Sq(lst,i,e);
print(lst);
cout<<"请问需要取第几个元素?"<<endl;
cin>>i;
GetElem_Sq(lst,i,e);
cout<<"第"<<i<<"个元素是"<<e<<endl<<endl;
cout<<"要查询哪个元素?"<<endl;
cin>>e;
n = LocateElem_Sq(lst,e);
if(n!=0)
cout<<"成功找到元素,在第"<<n<<"个位置"<<endl;
else
printf("没有找到该元素\n");
cout<<"现在清空线性表!"<<endl;
ClearList_Sq(lst);
printf("线性表长度为:%d\n",GetLength_Sq(lst));
return 0;
}
三、线性表的链式表示和实现
(1)概念:链式存储结构,结点在存储器中的位置是任意的,即逻辑上相邻的数据元素在物理上不一定相邻;与上面提到的顺序存储不同,链式存储在计算机内存中的表示是随机的,它只是在逻辑是相邻的,物理是不相邻;线性表的链式表示又称为非顺序映像或链式映像;链表是通过指针来进行实现的;
(2)链表的相关术语:链表是通过每个结点连接在一起来实现的,所以每个结点都由两个域组成。一、数据域:存储元素数值数据;二、指针域:存储直接后继结点的存储位置;所以由许多个结点组成的表就叫链表。链表中还有头指针,头结点,首元结点。头指针是指向链表中第一个结点的指针,首元结点是指链表中存储第一个数据元素a1的结点,头结点是在链表的首元结点之前附设的一个结点;数据域内只放空表标志和表长等信息。
(3)链表的分类:结点只有一个指针域的链表,称为单链表或线性链表;有两个指针域的链表,称为双链表;首尾相接的链表称为循环链表;
四、单链表的定义和实现 ##
(1)概念:单链表是由表头唯一确定,因此单链表可以用头指针的名字来命名;若头指针名是L,则把链表称为表L;
(2)下面用代码介绍单链表的基本操作和实现:
# include <stdio.h>
# include <stdlib.h>
# include <iostream>
using namespace std;
# define OK 1
# define ERROR 0
typedef int ElemType;
typedef int Status;
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
Status InitList_L(LinkList &L){
L = new LNode;
L->next = NULL;
return OK;
}
Status DestroyList_L(LinkList &L){
LinkList p;
while(L){
p=L;
L=L->next;
delete p;
}
return OK;
}
Status ClearList_L(LinkList &L){
LinkList p,q;
p=L->next;
while(p)
{
q=p->next;
delete p;
p=q;
}
L->next=NULL;
return OK;
}
int ListLength_L(LinkList L){
LinkList p;
p=L->next;
int i=0;
while(p){
i++;
p=p->next;
}
return i;
}
int IsEmpty_L(LinkList L){
if(L->next)
return 0;
else
return 1;
}
Status GetElem_L(LinkList L,int i,ElemType &e){
LinkList p;
p=L->next;
int j=1;
while(p&&j<i){
p=p->next;
++j;
}
if(!p || j>i)
return ERROR;
e=p->data;
return OK;
}
int LocateELem_L (LinkList &L,ElemType e) {
LinkList p;
p=L->next;
int j=1;
while(p != NULL){
if(p->data != e){
++j;
p=p->next;
}
else
break;
}
return j--;
}
Status ListInsert_L(LinkList &L,int i,ElemType e){
LinkList p,s;
p=L;
int j=0;
while(p && j<i-1){
p = p->next;
++j;
}
if(!p || j>i-1)
return ERROR;
s=new LNode;
s->data=e;
s->next=p->next;
p->next=s;
return OK;
}
Status ListDelete_L(LinkList &L,int i,ElemType &e){
LinkList p,q;
p=L;
int j=0;
while(p->next && j<i-1){
p=p->next;
++j;
}
if(!(p->next) || j>i-1)
return ERROR;
q=p->next;
p->next=q->next;
e=q->data;
delete q;
return OK;
}
Status print(LinkList L){
LinkList p;
p = L->next;
while(p != NULL){
cout<<p->data<<endl;
p = p->next;
}
return OK;
}
int main(){
int i,n;
ElemType e;
LinkList L;
InitList_L(L);
cout<<"请输入链表的长度:"<<endl;
cin>>n;
for(i=1; i<=n;i++){
cout<<"请输入第"<<i<<"个元素:"<<endl;
cin>>e;
ListInsert_L(L,i,e);
}
n = ListLength_L(L);
cout<<"插入完毕,表的长度是:"<<n<<endl;
printf("\n");
if(IsEmpty_L(L) == 0)
cout<<"表不为空,内容是:"<<endl;
print(L);
cout<<"请输入你要查找的元素:"<<endl;
cin>>e;
n = LocateELem_L(L,e);
if(n != 0)
cout<<"查找成功,元素在第"<<n<<"个位置"<<endl;
else
cout<<"查找失败,没有找到元素"<<endl;
printf("\n");
cout<<"请问你想删除第几个元素:"<<endl;
cin>>i;
ListDelete_L(L,i,e);
cout<<"元素删除成功!"<<endl;
print(L);
printf("\n");
cout<<"请问你想获取哪个位置的元素?"<<endl;
cin>>i;
GetElem_L(L,i,e);
cout<<"获取成功,第"<<i<<"个位置的元素是:"<<e<<endl;
cout<<"操作结束,现在清空链表!"<<endl;
ClearList_L(L);
n = ListLength_L(L);
cout<<"清空完毕,链表的长度为:"<<n<<endl;
DestroyList_L(L);
return 0;
}