- 单链表
也就是线性表的链式存储,它是指通过一组任意的存储单元来存储线性表中的数据元素,每个链表结点包含存放数据元素的数据域(data域)和存放后继结点的指针域
单结点的结点类型描述
typedef struct LNode
{
Elemtype data;
struct LNode *next;
}LNode,*Linklist;
//或
typedef struct LNode
{
int data;
struct LNode *next;
}LNode;
利用单链表可以解决顺序表需要大量连续存储空间的特点,但是单链表附加了指针域,也存在浪费存储空间的缺点。因为单链表的元素是离散地分布在存储空间中,所以单链表是非随机存储的存储结构
双链表结点定义
typedef struct DLNode
{
int data;
struct DLNode *prior;
struct DLNode *next;
}DLNode;
//另一种定义方式如上类推
单链表基本操作
- 头插法
LinkList List_headInsert(Linklist &L)
{
LNode *s;
int x;
L=(Linklist)malloc(sizeof(LNode));//malloc函数创建头结点
L->next=NULL;//初始为空链表
scanf("%d",&x);
while(x!=500)
{
s=(LNode*)malloc(sizeof(LNode));
s->data=x;
s->next=L->next;
L->next=s;
scanf("%d",&x);
}
return L:
}
//或
void createlistD(LNode *&c,int a[],int n)
{
LNode *s;
int i;
c=(LNode*)malloc(sizeof(LNode));
c->next=NULL;
for(int i=0;i<n;i++)
{
s=(LNode*)malloc(sizeof(LNode));
s->data=a[i];
s->next=c->next;
c->next=s;
}
}
- 尾插法
void createlistw(LNode *&C,int a[],int n)
{
LNode *s,*r;//r始终指向c的终端结点
int i;
c=(LNode*)malloc(sizeof(LNode));
c->next=NULL;
r=c;//r指向头结点,此时头结点就是终端结点
for(i=0;i<n;i++)
{
s=(LNode*)malloc(sizeof(LNode));
s->data=a[i];//用新申请的结点接收数组a中的元素
r->next=s;//用r来接纳新结点
r=r->next;//r指向终端结点以便接收下一个到来的结点
}
r->next=NULL;//c建立完成
}
- 按序号查找结点值
LNode *GetElem(LinkList L,int i)
{
int j=1;
LNode *p=L->next;
if(i=0)
return L;
if(i<1)
return NULL;
while(p&&j<i)
{
p=p->next;
j++;
}
return p;
}
- 按值查找表结点
LNode *LocateElem(linklist L,ElemType e)
{
LNode *p=L->next;
while(p!=NULL&&p->data!=e)
p=p->next;
return p;
}
- 插入结点操作
p=GetElem(L,i-1);//查找插入位置的前驱结点
s->next=p->next;
p->next;
- 删除结点
p=GetElem(L,i-1);//查找删除位置的前驱结点
q->next;
p-next=q->next;
free(q);
- 双链表尾插法
void createDlistW(DLNode *&L,int a[],int n)
{
DLNode *s,*r;
int i;
L=(DLNode*)malloc(sizeof(DLNode));
L->prior=NULL;
L->next=NULL;
r=L;//r始终指向终端结点
for(i=0;i<n;i++)
{
s=(DLNode*)malloc(sizeof(DLNode));
s->data=a[i];
//以下3句将s插入L的尾部
r->next=s;
s->prior=r;
r=s;
}
r->next=NULL;
}//尾插法很好理解,就不画图了
- 插入结点
s->next=p->next;
s->prior=p;
p->next=s;
s->next->prior=s;
- 删除结点
q=p->next;
p->next=q.>next;
q->next->prior=p;
free(q);
循环链表
- 循环单链表
循环单链表和单链表的区别就是表中最后一个结点的指针不是NULL,而改为指向头结点,从而整个链表形成一个环
在循环单链表中,表尾结点*r的next域指向L,故表中没有指针域为NULL的结点,所以循环单链表的判空条件不是头结点的指针是否为空,而是它是否等于头指针
若设置头指针,对表尾进行操作时需要O(n)的时间复杂度,设置尾指针r,r->next即为头指针,对于表头与表尾进行操作都只需要O(1)的时间复杂度
- 循环双链表
在循环双链表中,头结点的prior指针还要指向表尾结点
- 静态链表
静态链表是借助数组来描述线性表的链式存储结构,结点同样也有数据域data和指针域next,但这里的指针是结点的相对地址,也就是数组下标,又称为游标
#define maxsize 50
typedef struct
{
ElemType data;
int next;
Slist[maxsize];