前言
本章主要详解了线性表(逻辑结构)对应的顺序表和链表(存储结构)的实现方式,其中包含增删改查的操作的多种实现方法及代码,最后还介绍了一些特殊链表的引入,以解决现有的存储结构存在的一些问题缺陷。
文章目录
总览:
①线性表的定义和基本操作
定义:
线性表是具有相同类型的n(n>=0)个元素的有限序列,其中n为表长,n=0,该表为空表。
线性表的特点:
1.表中元素个数有限。
2.表中元素具有逻辑上的顺序性,在序列中各个元素排序有其先后次序。
3.表中元素都是数据元素,每个元素都是单个元素。
4.表中元素的数据类型都相同,这意味着每个元素占有相同大小的存储空间。
5.表中元素具有抽象性,即讨论元素间一对一的逻辑关系,而不考虑元素究竟表示的内容。
6.线性表是一种逻辑结构,表示元素之间一对一相邻的关系。
线性表的九种基本操作:
InitList(&L):初始化表。构造一个空的线性表.
DestroyList(&L):销毁操作。销毁线性表,并释放线性表所占用的内存空间。
LocateElem(L,e):按值查找操作。在表中查找具有给定关键字值得元素。
GetELem(L,i):按位查找操作。获取表中第个位置的元素的值。
ListInsert(&L,e):插入操作,在表中的第个位置上插入指定元素e。
ListDelete(&L,&e):删除操作。删除表L中第个位置的元素,并用e返回删除元素的值。
Printlist(u):输出操作。按前后顺序输出线性表的所有元素值。
Empty(L):判空操作。若为空表,则返回TRUE否则返回 FALSE。
Length(u):求表长。返回线性表L的长度,即中数据元素的个数。
②线性表的顺序表示
顺序表的定义:
线性表的顺序存储,又称顺序表。
数组静态分配:
#define Maxsize=50
typedef struct{
Elemtype data[Maxsize];
int length;
}sqlist;
数组动态分配:
typedef struct{
Elemtype *data;
int length;
}sqlist;
data =new Elemtype[Initsize];//动态获取分配空间;
顺序表的基本操作的实现:
插入操作:
bool InsertList(sqlist &L,int i,Elemtype e){
//i对应的是顺序表的表号,而不是数组的下标。
if(i<1||i>L.length+1)
return false;//插入位置是否合法
if(L.length>Maxsize)
return false;//是否有足够的插入空间
for(int j=L.length;j>=i;j--){
L.data[j]=L.data[j-1];
}
L.data[j]=e;
L.length++;
return true;
}
删除操作:
bool ListDelete(sqlist &L,int i,Elemtype &e){
if(i<1||i>L.length)
return false;
e=L.data[i-1];
for(int j=i;j<=L.length;j++){
L.data[j-1]=L.data[j];
}//采用覆盖的方式进行删除
L.length--;
return true;
}
按值查找:
int LocateElemtype(sqlist L,Elemtype e){
for(int j=0;j<L.length;j++){
if(L.data[j]==e)
return j+1;
}
return 0;
}
顺序表的合并操作:
void Array_imerse(int* L1,int* L2,int* L){
int k=0,i=0,j=0;
for(;i<len(L1)&&j<len(L2);){
if(L1[i]<L2[j])
L[k++]=L1[i++];
else
L[k++]=L2[j++];
}
while(i<len(L1)){
L[k++]=L1[i++];
}
while(j<len(L2)){
L[k++]=L2[j++];
}
}
③线性表的链式表示
单链表的定义:
线性表的链式存储,又称单链表。
单链表的结构:
typedef struct{
Elemtype data;
struct Lnode *next;
}Lnode,*linklist;
注意:Lnode*等价于linklist;
引入头结点的单链表:
优点:
1.链表的第一个位置和其他位置的操作统一。(插入操作)
2.空表和非空表的操作统一。
单链表的基本操作的实现:
头插法建立单链表:
linklist linklist_HeadInsert(linklist &L){
Lnode* s;int x;//s->data=x;
//初始化头结点
L=(linklist)malloc(sizeof(londe));
L->next=NULL;
scanf("%d",&x);
while(x!=9999){
s=(Lnode*)malloc(sizeof(londe));
s->next=L->next;
L->next=s;
scanf("%d",&x);
}
return L;
}
尾插法建立单链表:
linklist linklist_TailInsert(linklist& L){
Lnode* s,*r=L;int x;
L=(linklist)malloc(sizeof(Lnode));
scanf("%d",&x);
while(x!=9999){
s=(Lnode*)malloc(sizeof(Lnode));
s->data=x;
r->next=s;
r=s;
scanf("%d",&x);
}
r->next=NULL;
return linklist;
}
按序号查找&按值查找:
//按序号查找
Lnode* GetElem(linklist L,int i){
Londe *p=L->next;
int j=1;
if(i==0)//如果是i=0,返回头结点
return L;
if(i<0)//如果i<0,返回NULL
return NULL;
while(p&&j<i){//p不为空且j<i;
p=p->next;
j++;
}
return p;
}
//按值查找
int ElemLocate(linklist L,int x){
Londe* p=L->next;int j=1;
while(p&&p->data!=x){
p=p->next;
j++;
}
return j;
}
插入节点操作:
bool linklist_BackInsert(linklist &L,int i,int e){
Lnode* p=GetElem(L,i-1);
if(p==NULL)
return false;
Lnode* q=(Londe*)malloc(sizeof(lnode));
q->data=e;
q->next=p->next;
p->next=q;
}
删除节点操作:
void linklist_LnodeDelete(Lnode* p){
Lnode* q=p->next;
p->next=q->next;
free(q);
}
单链表的逆置操作:
linklist* linklist_LondeInverse(linklist &L){
Lnode* p=L;//拿到单链表头部的指针
while(p->next){
p=p->next;
}
Lnode* r=p;//拿到单链表尾部的指针
Lnode* q;//q作为p->next的节点指针
p=L;//p作为头结点指针,指向head节点
while(p->next!=r){
q=p->next;//拿到第一个节点node(L->next节点)
p->next=q->next;//将该节点插入到r节点的后面,使用插入操作
q->next= r->next;
r->next=q;
}
return p;
}
单链表的合并操作:
//合并后,数据从大到小依次排列
linklist* linklist_immerse(linklist &L1,linklist &L2){
Lnode* r=L1;
Lnode *p=L1->next,*q=L2->next;
while(p&&q){
if(p->data<q->data){
p->next=r->next;
r->next=p->next;
p=p->next;
}
else{
q->next=r->next;
r->next=q->next;
q=q->next;
}
}//使用头插法合并链表
while(p){
p->next=r->next;
r->next=p->next;
p=p->next;
}
while(q){
q->next=r->next;
r->next=q->next;
q=q->next;
}
free(p);free(q);
return r;
}
//合并后,数据从小到大依次排列
linklist* linklist_immerse(linklist &L1,linklist &L2){
Lnode* r=L1;
Lnode *p=L1->next,*q=L2->next;
while(p&&q){
if(p->data<q->data){
r->next=p;
p=p->next;
r=r->next;
}
else{
r->next=q;
q=q->next;
r=r->next;
}
}//使用尾插法合并链表
if(p){
r->next=p;
}
if(q){
r->next=q;
}
free(p);free(q);
return L1;
}
④特殊链表
双链表
双链表的结构:
typedef struct{
Elemtype data;
struct Dnode *prior,*next;
}Dnode,*Dlinklist;
双链表的插入操作:
注意:
双链表的表尾位置的插入操作和表头位置的插入操作是不一样的,因为表尾为空NULL并且没有prior指针。