单链表的结点:数据域,指针域(存储下一结点的地址)
包含函数:初始化,销毁,清空,尾插法和头插法批量录入数据,统计结点的个数,追加结点,删除结点,正序和逆序打印链表。
知识点:
(1)一个结构体内部不能含有结构体本身类型的结点,但可以含有本类型的指针。
(2)易错点:删除,插入的操作可能会影响首结点的地址,要单独处理,不注意代码运行会全是bug!
(3)逆序打印采用的递归,可着重看一下。
(4)批量录入数据有两种方法:头插法,链表的顺序和输入顺序正好相反。尾插法则正好相同。
(5)删除结点采用O(1)方法,分4种情况
•首结点&&最后一个结点:*L = null
•首结点&&不是最后一个结点:先保存下一结点的地址,用下一结点覆盖本应删除的目的结点,删除事先保存的结点
•不是首结点&&最后一个结点:无法删除,必须采用伴随扫描指针的方式,获知前驱指针,才能删除
•不是首结点&&不是最后一个结点:采用情况2的方法
(6)伴随指针查找value的代码(两个紧邻指针一起扫描单链表,一般删除结点时使用)
//至少含有一个元素,即不为空
p = frist; q = NULL;
while (p != NULL && p->data != value)
{
//在此通过p可以操作所有的元素
q = p;/*这两个语句是不可分割的,是一个整体,相当于原语*/
p = p->next;/*在这个整体前后,q一定指向p的前驱*/
//在此p:2 to last;q:1 to last - 1
}
/*出循环后,q仍旧指向p的前驱,只要p不指向空*/
/*适用于查找value,并进行牵扯到其前驱的操作*/
注意第一个结点就是value的情况!,出循环后前驱指针是null
#include"头文件.h"
/*头插法,逆序
尾插法,正序*/
typedef struct node {
int data;
struct node *next;
}Node,*LinkList;
/*初始化单链表*/
void InitList(LinkList *L) {
*L = null;
}
/*销毁单链表*/
void DestroyList(LinkList *L) {
if (*L == null)
return;
LinkList p;
while (*L != null) {
p = (*L)->next;//临时保存下一结点的地址
free(*L);
*L = p;
}
}
/*清空单链表*/
void ClearList(LinkList *L) {
DestroyList(L);
}
/*批量录入数据:头插法*/
void HeadCreate(LinkList *L) {
int elem; Node *p;
while (scanf_s("%d", &elem), elem != -1) {
if (*L == null) {
*L = (LinkList)malloc(sizeof(Node));
if (*L == null) exit(-1);
(*L)->data = elem;
(*L)->next = null;
}
else {
p = (LinkList)malloc(sizeof(Node));
if (!p) exit(-1);
p->data = elem;
p->next = (*L)->next;
(*L)->next = p;
}
}
}
/*批量录入数据:尾插法*/
void TailCreate(LinkList *L) {
int elem; Node *tail = null,*p;
while (scanf_s("%d", &elem), elem != -1) {
if (*L == null) {
*L = (LinkList)malloc(sizeof(Node));
if (*L == null) exit(-1);
(*L)->data = elem;
(*L)->next = null;
tail = *L;
}
else {
p = (LinkList)malloc(sizeof(Node));
if (!p) exit(-1);
p->data = elem;
p->next = null;
tail->next = p;
tail = p;
}
}
}
/*统计结点的个数*/
int TotalNum(LinkList *L) {
int count = 0;//计数器
LinkList p = *L;
for (; p; p = p->next)
++count;
return count;
}
/*在表尾追加元素value*/
void AddToTail(LinkList *L,int value) {
Node *p = null,*q = null;
if (*L == null) {
*L = (LinkList)malloc(sizeof(Node));
if (*L == null) exit(-1);
(*L)->data = value;
(*L)->next = null;
}
else {
for (p = *L; p->next != null; p = p->next)
;
q = (LinkList)malloc(sizeof(Node));
if (!q) exit(-1);
q->data = value;
q->next = p->next;
p->next = q;
}
}
/*删除第一个值是value结点*/
void Remove(LinkList *L,int value) {
if (*L == null)
return;
Node *p = *L,*q;
while (p && p->data != value) {
p = p->next;
}
if (!p) {
printf("没有该元素!\n"); return;
}
if (p == *L) {
if (p->next == null) {
*L = null;
free(p);
}
else {
p = (*L)->next;
(*L)->data = (*L)->next->data;
(*L)->next = (*L)->next->next;
free(p);
}
}
else {
if (p->next != null) {
p->data = p->next->data;
q = p->next;
p->next = q->next;
free(q);
}
else {
printf("无法删除,请采用伴随扫描指针的方法删除。\n");
return;
}
}