1 原理
顺序表的缺点:
- 插入和删除移动大量元素
- 数组的大小不好控制
- 占用一大段连续的存储空间,造成很多碎片
链表规避了上述顺序表缺点

逻辑上相邻的两个元素在物理位置上不相邻

头结点
L:头指针

头指针:链表中第一个结点的存储位置,用来标识单链表。
头结点:在单链表第一个结点之前附加的一个结点,为了操作上的方便。
若链表有头结点,则头指针永远指向头结点,不论链表是否为空,头指针均不为空,头指针是链表的必须元素,他标识一个链表。头结点是为了操作的方便而设立的,其数据域一般为空,或者存放链表的长度。有头结点后,对在第一结点前插入和删除第一结点的操作就统一了,不需要频繁 重置头指针。但头结点不是必须的。
优缺点
优点:
- 插入和删除操作不需要移动元素,只需要修改指针
- 不需要大量的连续存储空间
缺点:
- 单链表附加指针域,也存在浪费存储空间的缺点
- 查找操作时需要从表头开始遍历,依次查找,不能随机存取
2 表示
2.1 定义
cpp
typedef int ElemType ;
typedef struct LNode{ //单链表结点类型
ElemType data; //数据域
struct LNode* next;//指针域
}LNode, *LinkList;
2.2 新建链表
2.2.1 头插法新建链表

cpp
void list_head_insert(LinkList &L)
{
ElemType x;
LNode *s;
L= (LinkList)malloc(sizeof(LNode));//申请头节点空间
L->next = NULL;
scanf("%d",&x);
while(x!=9999)
{
s= (LinkList)malloc(sizeof(LNode));//申请节点空间
s->data = x;
s->next = L->next;//指向原本第一个节点
L->next = s; //头结点的next
scanf("%d",&x);
}
}
2.2.2 尾插法新建链表

cpp
void list_tail_insert(LinkList &L)
{
L= (LinkList)malloc(sizeof(LNode));//申请头节点空间
ElemType x;
LNode *s, *r = L;//s是用来指向新节点,r始终指向链表尾部
L->next = NULL;
scanf("%d", &x);
while(x!=9999)
{
s = (LinkList) malloc(sizeof(LNode));
s->data=x;
r->next = s;
r=s;
scanf("%d", &x);
}
r->next=NULL;//让为节点的next=NULL
}
2.3 打印链表
cpp
void print_list(LinkList L)
{
L = L->next;
while(L != NULL)
{
printf("%3d",L->data);
L =L->next;
}
printf("\n");
}
2.4 查找
2.4.1 按位置查找
++头节点代表第0个位置++

cpp
//按位置查找
LinkList GetElem(LinkList L, int SearchPos)
{
int i = 0;
if(SearchPos < 0)
{
return NULL;
}
while(L && i < SearchPos)
{
L = L->next;
i++;
}
return L;
}
2.4.2 按值查找

cpp
//按值 查找
LinkList LocateElem(LinkList L, ElemType SearchVal)
{
while(L)
{
if(L->data ==SearchVal)
{
return L;
}else
{
L =L->next;
}
}
return NULL;
}
2.5 插入

插入情况

cpp
bool ListFrontInsert(LinkList L, int InsertPose, ElemType InsertValue)
{
LinkList p = GetElem(L, InsertPose-1);
if(p == NULL)
{
return false;
}
LinkList q ;
q =(LinkList)malloc(sizeof(LNode));
q->data = InsertValue;
q->next = p->next;
p->next = q;
return true;
}
2.6 删除
删除注意的点:
- 需要释放删除节点的空间
- 需要判断删除的位置是否存在
cpp
void dele_elem(ListLink L, int pos) {
if (pos <0) {
return ;
}
ListLink r,q; //q用来存储要删除的节点
r = find_elem(L, pos -1);
if (NULL == r) {
return;
}
q=r->next;
if (q==NULL)
{return;}
r->next = q->next;//断链
free(q);
q = NULL;//防止野指针
}
引用:要不要对变量进行赋值,如果不用不加引用,若要加引用