概述
在计算机中用一组任意的,可能是连续的,也可能是不连续的存储单元存储线性表的数据元素,称为链式存储结构。和顺序表相比的优势(使用场景):
因为不确定链式存储结构的存储单元是否连续,所以链表的结点不可以随机存取。
链表中的数据是以结点来表示的,每个结点的构成:
- 数据域(存储数据元素的映像)
- 指针域(存储后继元素存储位置)
单链表
n个结点链成的一个链表,当每个结点中只包含一个指针域时,称为单链表
- 开始结点无直接前趋:头指针head指向开始结点
- 终端结点无后继结点:终端结点指针域为NULL
因此,一个单链表可由头指针唯一确定,并且可以用头指针的名字命名。
1 2 3 4 5 6 7 8 9 10 11
| typedef char Datatype;
typedef struct node { Datatype data; struct node *next; } ListNode;
typedef ListNode *LinkList;
|
将新结点插入到当前链表表头,直到读入结束标志,如图所示
代码如下,这里指定回车为结束标志
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| LinkList CreateListF() { LinkList head; ListNode *p; Datatype ch; head = NULL; while (1) { ch = getchar(); if (ch == '\n') { break; } p = (ListNode *)malloc(sizeof(ListNode)); p->data = ch; p->next = head; head = p; } return head; }
|
需要一个尾指针rear,始终指向链表的尾结点,如图
代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| LinkList CreateListR() { LinkList head, rear; ListNode *p; char ch; head = NULL; rear = NULL; while (1) { ch = getchar(); if (ch == '\n') { break; } p = (ListNode *)malloc(sizeof(ListNode)); p->data = ch; if (head == NULL) { head = p; } else { rear->next = p; } rear = p; } if (rear != NULL) { rear->next = NULL; } return head; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| ListNode *GetNode(LinkList head, int i) { ListNode *p = head; int j = 0; while (++j < i && p) { p = p->next; } return j == i ? p : NULL; }
|
- 查找某个值的结点位置,同样的,时间复杂度为O(n)
1 2 3 4 5 6 7 8 9 10 11 12 13
| ListNode *LocateNode(LinkList head, Datatype k) { ListNode *p = head; while (p && p->data != k) { p = p->next; } return p; }
|
- 插入运算,最重要的是先找到插入位置的的前一个结点…,所以依然时间复杂度0(n)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| void InsertList(LinkList head, int i, Datatype x) { ListNode *p, *s; p = GetNode(head, i - 1); if (p == NULL) { printf("error position"); exit(0); } s = (ListNode *)malloc(sizeof(ListNode)); s->data = x; s->next = p->next; p->next = s; }
|
- 删除运算,同理,最重要的是先找到删除结点的前一个结点…,时间复杂度O(n)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| Datatype DeleteList(LinkList head, int i) { ListNode *p, *s; Datatype x; p = GetNode(head, i - 1); if (p == NULL) { printf("error position"); exit(0); } s = p->next; p->next = s->next; x = s->data; free(s); return x; }
|
单循环链表
单链表的最后一个结点(终端结点)的指针域不为空,而是指向链表的头节点,使整个链表构成一个环。