线性表是最简单、也是最基本的一种线性数据结构。它有两种存储方法:顺序表和链表,它一般有12种基本操作,主要基本操作是插入、删除和查找等。我这里把顺序表和单链表的这12种操作按自己的理解写了一遍,两两对照着看应该要好一点。
线性表12基本操作
准备(接下来也是这样比较,不做说明了)
顺序表(Sq —— SequenceList):
#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10
typedef char ElemType;
typedef struct{
ElemType *elem;
int length;
int listsize;
int incrementsize;
}SqList;
void ErrorMassage(char *s)
{
cout<<s<<endl;
exit(1);
}
void ListIncrement(SqList &L)
{
realloc(L.elem,(L.listsize+L.incrementsize)*sizeof(ElemType));
L.listsize+=L.incrementsize;
return;
}
单链表(L —— LinkList):
特别说明:我创建的单链表是有一个空的头结点,并不是直接取第一个结点做头结点,这点与本科书上的不相同
typedef char ElemType;
typedef struct LNode{
ElemType data;
struct LNode *next;
}LNode,*LinkList;
void ErrorMassage(char *s)
{
cout<<s<<endl;
exit(1);
}
一、InitList(&L):构造一个空的顺序表L
void InitList_Sq(SqList &L) //创建一个空的顺序表L,但是已经分配了内存
{
L.elem=new ElemType[LIST_INIT_SIZE];
L.length=0;
L.listsize=LIST_INIT_SIZE;
L.incrementsize=LISTINCREMENT;
return;
}
void InitList_L(LinkList &L,int n)
{
LNode *p,*q;
L=new LNode;
for(int i=0;i<n;i++)
{
q=new LNode;
q->data='A'+i;
if(i>0)
p->next=q;
else
L->next=q;
p=q;
}
q->next=NULL;
return;
}
二、ListInsert(&L,i,e):在第i个元素前插入新元素e
void ListInsert_Sq(SqList &L,int i,ElemType e) //将元素e插入到顺序表第i个位置之前
{
if(i<1||i>L.length+1) ErrorMassage("i is invalid!");
if(L.length>=L.listsize) ListIncrement(L);
ElemType *p,*q;
p=&L.elem[i-1];
for(q=&L.elem[L.length-1];q>=p;q--)
*(q+1)=*q;
*p=e;
L.length++; //插入一个元素后L长度加1
return;
}
void ListInsert_L(LinkList &L,LNode *q,LNode *s) //在q前插入新结点s
{
LNode *p=L;
for(;p->next!=q&&p->next;p=p->next);
s->next=p->next;
p->next=s;
return;
}
三、ListDelete(&L,i,&e):删除第i个元素,存入e中
void ListDelete_Sq(SqList &L,int i,ElemType &e) //删除L的第i个元素,并用e返回其值
{
if(i<1||i>L.length) ErrorMassage("i is invalid!");
ElemType *q;
e=L.elem[i-1];
for(q=&L.elem[i-1];q<=&L.elem[L.length-1];q++)
*q=*(q+1);
L.length--; //删除一个元素后L长度减1
return;
}
void ListDelete_L(LinkList &L,LNode *q,ElemType &e) //删除L中的q结点,并用e返回其内元素值
{
LNode *p;
p=L;
for(;p->next!=q&&p->next;p=p->next);
p->next=p->next->next;
e=q->data;
delete q;
return;
}
四、LocateElem(L,e):返回第1个与e相等元素的位序
int LocateElem_Sq(SqList L,ElemType e) //返回L中第1个与e相等的元素的位序,没有则返回0
{
int i;
for(i=0;i<L.length;i++)
if(L.elem[i]==e) return i+1;
if(i==L.length) return 0;
}
int LocateElem_L(LinkList L,ElemType e) //返回L中第1个与e相等元素的位序,若不存在返回0
{
LNode *p;
int i;
p=L->next;
for(i=1;p;i++,p=p->next)
if(p->data==e)
return i;
return 0;
}
五、GetElem(L,i,&e):用e返回第i个元素的值
void GetElem_Sq(SqList L,int i,ElemType &e) //用e返回L中第i个元素的值
{
if(i<1||i>L.length) ErrorMassage("i is invalid!");
e=L.elem[i-1];
return;
}
void GetElem_L(LinkList L,int i,ElemType &e) //用e返回L中第i个结点中元素的值
{
if(i<1||i>ListLength_L(L))
ErrorMassage("i is invalid!");
LNode *p;
p=L->next;
for(int j=1;j!=i&&p;p=p->next,j++);
e=p->data;
return;
}
六、DestroyList(&L):销毁线性表L
void DestroyList_Sq(SqList &L) //销毁顺序表
{
delete []L.elem;
L.length=0; //顺序表销毁后长度为0,数组空间为0
L.listsize=0;
return;
}
void DestroyList_L(LinkList &L) //销毁链表
{
LNode *p,*q;
q=L->next;
while(q)
{
p=q->next;
delete q;
q=p;
}
delete L;
return;
}
七、ListLength(L):返回L中元素个数
int ListLength_Sq(SqList L) //返回顺序表L的当前长度
{
return L.length;
}
int ListLength_L(LinkList L) //返回L所指链表的长度
{
LNode *q;
int l=0;
q=L->next;
while(q)
{
l++;
q=q->next;
}
return l;
}
八、ListTraverse(L):依次输出L中每个元素
void ListTraverse_Sq(SqList L) //依次输出L中的每个元素
{
int i=0;
if(L.length<=0) return;
for(i=0;i<L.length-1;i++)
cout<<L.elem[i]<<" ";
cout<<L.elem[i]<<endl;
return;
}
void ListTraverse_L(LinkList L)
{
LNode *q;
q=L->next;
while(q)
{
cout<<q->data<<" ";
q=q->next;
}
cout<<endl;
return;
}
九、ClearList(&L):将L重置为空表
void ClearList_Sq(SqList &L) //将L置为空表
{
for(int i=0;i<L.length;i++)
L.elem[i]='\0';
L.length=0; //置为空表后长度为0
return;
}
void ClearList_L(LinkList &L)
{
DestroyList_L(L->next);
L->next=NULL;
return;
}
十、LIstEmpty(L):若L为空表返回True,否则返回False
bool ListEmpty_Sq(SqList L) //判断L是否为空表,若是返回true,否则返回false
{
if(L.length==0) return true;
else return false;
}
bool ListEmpty_L(LinkList L)
{
int i;
LNode *p;
p=L->next;
for(i=0;p;p=p->next,i++);
if(i)
return false;
else
return true;
}
十一、PriorElem(L,cur_e,&pre_e):用pre_e返回cur_e的前驱
ElemType PriorElem_Sq(SqList L,ElemType e) //返回e的前驱元素,若e是第一个或者不是L中元素则输出提示信息
{
int i=LocateElem_Sq(L,e);
if(i<=1) ErrorMassage("No priorelem!");
else return L.elem[i-2];
}
LNode* PriorElem_L(LinkList L,ElemType cur_e)
{
LNode *p;
p=L->next;
if(LocateElem_L(L,cur_e)<=1)
ErrorMassage("No priornode!");
while(p->next->data!=cur_e)
p=p->next;
return p;
}
十二、NextElem(L,cur_e,&next_e):返回后继
ElemType NextElem_Sq(SqList L,ElemType e) //返回e的后继元素,若e是最后一个或者不是L中元素则输出提示信息
{
int i=LocateElem_Sq(L,e);
if(i==0||i==L.length) ErrorMassage("No nextelem!");
else return L.elem[i];
}
LNode* NextElem_L(LinkList L,ElemType cur_e)
{
LNode *p;
p=L->next;
int i=LocateElem_L(L,cur_e);
if(i<1||i>=ListLength_L(L))
ErrorMassage("No nextelem!");
for(;p->data!=cur_e;p=p->next);
return p->next;
}