引言:线性表是最常用且最简单的一种数据结构,同时也是相当灵活的一种数据结构,它的存储方式可大致分为顺序存储和链式存储两种,对线性表的数据元素不仅可以进行访问,还可以进行插入和删除等。
一、顺序表的表示和实现
线性表的顺序表示指的是用一组地址连续的存储单元依次存储线性表的数据元素,这种存储结构是一种随机存取的存储结构
1.线性表的动态分配顺序存储结构
#define TRUE 1
#define FALSE 0
#define OK 1
#define FALSE 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status; //本文用整型数据类型进行实验
#define LIST_INIT_SIZE 100 //线性表存储空间的初始分配量
#define LISTINCREMENT 10 //线性表存储空间的分配增量
typedef int ElemType;
typedef struct
{
ElemType *elem; //存储空间基址
int length; //当前长度
int listsize; //当前分配的存储容量(以 sizeof(ElemType)为单位)
}SqList;
2.顺序表的构造、插入、删除、查找
Status InitList_Sq(SqList &L) //构造一个空的线性表
{
L.elem=(ElemType *)malloc(LIST_INIT_SIZE * sizeof(ElemType));
if(!L.elem)
exit(OVERFLOW);
L.length=0;
L.listsize=LIST_INIT_SIZE;
return OK;
}
Status ListInsert_Sq(SqList &L, int i,ElemType e) //在顺序表L中第i个位置之前插入元素e
{
if(i<1 || i>L.length+1)
return ERROR; //i值不合法
if(L.length >= L.listsize) //增加分配存储空间
{
newbase= (ElemType *)malloc(L.elem,(L.length+LISTINCREMENT)*sizeof(ElemType));
if(!newbase)
exit(OVERFLOW); //存储空间分配失败
L.elem=newbase;
L.listsize += LISTINCREMENT;
}
q= &(L.elem[i-1]); //q为插入位置
for(p= &(L.elem[L.length-1]);p>=q;--p)
*(p+1)=*p; //插入位置及以后的元素右移
*q=e;
++L.length; //表长加1
return OK;
}
Status ListDelete_Sq(SqList &L, int i,ElemType &e) //在顺序表L中删除第i个元素,并用e返回其值
{
if(i<1 || i>L.length)
return ERROR; //i值不合法
p=&(L.elem[i-1]);
e=*p;
q=L.elem+L.length-1;
for(++p;p<=q;++p) //被删除元素之后的元素左移
*(p-1) = *p;
--L.length;
return OK;
}
Status LocateElem_Sq(SqList L,ElemType e,Status(* compare)(ElemType,ElemType))
{ //在顺序表L中查找第一个值与e满足compare()的元素的位序
i=1;
p=L.elem;
while(i<=L.length && !(*compare)(*p++,e))
i++;
if(i<=L.length)
return i;
else
return 0;
}
二、线性链表的表示和实现
线性表的链式存储结构的特点是用一组的任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)
1.线性表的单链表存储结构
#define TRUE 1
#define FALSE 0
#define OK 1
#define FALSE 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status; //本文用整型数据类型进行实验
typedef int ElemType;
typedef struct List
{
ElemType data;
struct List *next;
}List;
2.单链表的构造、插入、删除、逆置
List *creat(void) //单链表的构造
{
List *p,*head;
head=new List;
p=head;
int n=1,x;
cout<<"请输入数据(输入-1结束):";
while(n)
{
cin>>x;
if(x!=-1)
{
List *q=new List;
q->data=x;
p->next=q;
p=q;
}
else
{
n=0;
cout<<"输入结束"<<endl;
}
}
p->next=NULL;
return head;
}
Status ListInsert_L(List &L,int i,ElemType e) //在单链表第i个元素前插入元素e
{
List p=L,s;
int j=0;
while(p && j<i-1)
{
p=p->next;
++j;
}
if(!p || j>i-1)
return ERROR;
s=(List)malloc(sizeof(List)); //生成新结点
s->data=e;
s->next=p->next;
p->next=s;
return OK;
}
Status ListDelete_L(List &L,int i,ElemType &e)
{ //删除单链表第i个元素,用e返回其值
List p=L,q;
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;
free(q);
return OK;
}
Status Listoppose(List *l) //单链表的就地逆置
{
List *p,*q;
p=l;
p=p->next;
l->next=NULL;
while(p)
{
q=p;
p=p->next;
q->next=l->next;
l->next=q;
}
return OK;
}
三、C++标准模板库(list模板类)
list 模板类在 list 头文件中声明,表示双向链表;即除了第一个和最后一个元素外,每个元素都与前后的元素相连接,意味着可以双向遍历链表。实现元素的快速插入和删除