在了解完线性表的顺序存储(顺序表)之后,我们接下来要说的就是线性表的链式存储,一般叫做链表(单链表),值得一提的是上一节中顺序表的操作还有一些如合并等,希望读者自行学习。
接下来我将从3个方面来介绍线性表的链式存储(单链表or线性链表):
1.概念
首先,线性表是一种逻辑概念,线性表的实现方式(存储方式)有两种,一种就是顺序存储,得到的表也叫顺序表;另一种就是链式存储,得到的表也就叫链表。

一般情况下,每一个链表会有一个头指针(head),头指针指向首个结点,如果链表为空,那么头指针也肯定为空(可以作为判空条件)。
2.区别
这里详细再讲解一下两种存储的区别,如图为顺序存储的示意图,表中元素存储的物理地址是连续的。因此,在进行插入删除操作时需要对之后的元素全部进行位移操作(缺点)。但是这样可以随机存取。

而链表的物理存储地址是不连续的,如图。链式存储的优点就是操作方便,不需要像顺序存储一样对之后的元素进行操作,缺点时地址不连续,地址利用率低,不可以随机存取。为了实现逻辑上的线性,链表中每一个节点需要有着一个指针域,存放后继节点的物理地址。(双链表还有一个指向前继节点的位置的指针域)

3.操作算法
在这里提一嘴,我在网上看到在定义类的时候有使用typedef truct 的也有使用truct的,这里我简单说一下使用时的区别:
struct _x1
{
...
}x1;
是定义了类_x1和_x1的对象实例x1,使用时可以直接这样使用: x1.a=1 x1.b=2
因为x1已经是一个实例化对象了
typedef struct _x2
{
...
} x2;
是定义了类_x2和_x2的类别名x2 ,在使用时还需要实例化一个对象,
x2 target;
target.a=1;
target.b=2;这样使用
具体区别的可以看http://t.csdnimg.cn/1vUX8的博客。
同上节一样,链表的创建首先需要定义一个结点对象,结点包含数据与和指针域,因此代码如下(这里不使用类C语言,而是直接使用C语言):
#include <stdio.h>
#include <stdlib.h>
// 定义链表结点结构
typedef struct LNode {
int data;
struct LNode* next;
}LNode,*LinkList;
//typedef <数据类型><别名>
//LNode,*LinkList;这里等价于typedef struct LNode LNode 将结点这个数据类型重命名为LNode
// 以及 typedef struct LNode *LinkList 将指向结点的指针重命名为 LinkList
bool InitList(LinkList &L){//初始化链表
L = (LNode *)malloc(sizeof(LNode));//LNode *强调结点指针 LinkList强调指向的是一个链表(头指针)
if(L== NULL){
return false;
} //防止有脏数据
L->next=NULL;
}
void PrintList(LinkList L){//打印链表
LNode *temp = L->next;
while(temp!=NULL){
printf("%d ",temp->data);
temp=temp->next;
}
printf("\n");
}
bool InsertList(LinkList &L,int i,int x){//按位i插入数据x
if(i<1){
return false;
}
LNode *p;
p=L;
int j=0;
while(p!=NULL && j<i-1){//侧面体现链表不可以随机存取,
//顺序表可以根据结点大小,首结点位置和存放位置直接算出需要插入数据的位置
p=p->next;
j++;
}
LNode *s = (LNode*)malloc(sizeof(LNode));//申请一个结点空间存放X
s->next=p->next;//先将s结点的后继改为p的后继 这一步和下一步可以颠倒
s->data=x;//再将x存放在s结点的数据域
p->next=s;//将p的后继改为s结点,s结点至此接入链表中,此步不可同第一步颠倒,
//否则p->next被更改 链表会中断在s结点
return true;
}
bool DeleteList(LinkList &L,int i){//按位删除
if(i<1){
return false;
}
LNode *p;
p=L;
int j=0;
while(p!=NULL && j<i-1){
p=p->next;
j++;
}
LNode *temp = p->next;
p->next=temp->next;
return true;
}
LNode* GetInit(LinkList L,int i){//按位查找
if(i<1){
return NULL;
}
LNode *p;
p=L;
int j=0;
while(p!=NULL && j<=i-1){
p=p->next;
j++;
}
printf("%d",p->data);
return p;
}
bool ChangeInit(LinkList L,int i,int x){//按位修改
if(i<1){
return false;
}
LNode *p;
p=L;
int j=0;
while(p!=NULL && j<=i-1){
p=p->next;
j++;
}
p->data=x;
return true;
}
int main(){//测试案例
LinkList L;
InitList(L);
InsertList(L,1,1);
InsertList(L,2,2);
InsertList(L,3,3);
InsertList(L,4,4);
InsertList(L,5,5);
InsertList(L,6,6);
DeleteList(L,4);
ChangeInit(L,4,99);
PrintList(L);
GetInit(L,4);
}