线性链表
线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素(这些存储单元可以是连续的,也可以不连续)。
因此为了表示每个数据元素与其后继元素之间的逻辑关系,对于数据元素来说,除了储存其本身的信息之外,还需储存一个指示其直接后继的信息(即直接后继的存储位置)。这两部分组成数据元素的存储映像,称为结点(node)。
结点包括两个域:其中存储数据元素信息的域称为数据域;存储直接后继存储位置的域称为指针域。指针域中存储的信息称作指针或链。
n个结点链结成一个链表,即为线性表(a1, a2, ... ,an)
的链式存储结构。又由于此链表中每个结点中只包含一个指针域,故又称为线性链表或单链表。
单链表
gloab.h
#ifndef GLOBAL_H
#define GLOBAL_H
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#define OK 1 // 通过
#define ERROR 0 // 错误
#define OVERFLOW -2 // 堆栈上溢
#define UNDERFLOW -3 // 堆栈下溢
typedef int Status; // 函数类型,其值为状态码
typedef int ElemType; // 抽象数据类型
#endif // !GLOBAL_H
存储结构
// 线性表的单链表存储结构
typedef struct LNode
{
ElemType data;
struct LNode* next;
}LNode, * LinkList;
获取元素
Status GetElem_L(LinkList L, int i, ElemType* e)
{
// L为带头结点的单链表的头指针
// 当第i个元素存在时,其值赋给*e并返回OK,否则ERROR
LinkList p = L->next; // 初始化,p指向第一个结点
int j = 1; // 计数器
while (p && j < i) {
p = p->next;
++j;
}
if (!p || j > i) // 第i个元素不存在
return ERROR;
*e = p->data; // 第i个元素
return OK;
}
插入元素
Status ListInsert_L(LinkList L, int i, ElemType e)
{
// 在带头结点的单链线性表L中第i个位置之前插入元素e
LinkList p = L;
int j = 0;
while (p && j < i - 1)
{
p = p->next;
++j; // 寻找第i-1个结点
}
if (!p || j > i - 1)
return ERROR; // i小于1或者大于表长加1
LinkList s = (LinkList)malloc(sizeof(LNode)); // 生成新结点
s->data = e;
s->next = p->next; // 插入L中
p->next = s;
return OK;
}
删除元素
Status ListDelete_L(LinkList L, int i, ElemType* e)
{
// 在带头结点的单链线性表L中,删除第i个元素,用*e返回
LinkList p = L;
int j = 0;
while (p->next && j < i - 1) {
p = p->next; // 寻找第i个结点,并令p指向其前驱
++j;
}
if (!(p->next) || j > i - 1) {
return ERROR; // 删除位置不合理
}
LinkList q = p->next;
p->next = q->next;
if (e) *e = q->data;
free(q); // 删除并释放结点
return OK;
}
创建链表
LinkList CreateList_L(LinkList L, int n)
{
// 逆序位输入n个元素的值,建立带表头结点的单链线性表L
L = (LinkList)malloc(sizeof(LNode));
L->next = NULL; // 先建立一个带头结点的单链表
for (int i = n; i > 0; --i) {
LinkList p = (LinkList)malloc(sizeof(LNode)); // 生成新结点
scanf("%d", &p->data); // 输入元素的值
p->next = L->next;
L->next = p; // 插入到表头
}
return L;
}
遍历
Status ListTraverse_L(LinkList L, Status(*visit)(ElemType))
{
LinkList p = L->next;
while (p) {
if (visit(p->data)) {
p = p->next;
}
else {
return ERROR;
}
}
return OK;
}
测试
int main() {
LinkList L = CreateList_L(NULL, 5);
printf("\n创建后为:");
ListTraverse_L(L, PrintElement);
ListInsert_L(L, 3, 7);
printf("\n插入后为:");
ListTraverse_L(L, PrintElement);
ListDelete_L(L, 3, NULL);
printf("\n删除后为:");
ListTraverse_L(L, PrintElement);
}