1.链表初始化
2.链表销毁
3.链表清空
4.链表表长
5.取单链表中第i个元素的内容
6.查找运算「按值查找」
7.插入:在第i个结点前插入值为e的新结点
8.删除第i个结点
9.单链表的头插法
10.单链表的尾插法
————————
初始化:
// 假设 Status 是自定义状态类型,通常用于返回操作结果
// 这里简单模拟:0 表示失败,1 表示成功
typedef int Status;
#define OK 1
#define ERROR 0
// 定义链表结点结构
typedef struct LNode {
// 数据域,可根据实际需求替换类型
int data;
// 指向下一个结点的指针
struct LNode *next;
} LNode;
// 定义链表类型,本质是指向结点的指针
typedef struct LNode *LinkList;
// 初始化单链表(带头结点)
// &L 是链表指针的引用(C 语言中通过指针的指针模拟“引用”效果)
Status InitList_L(LinkList &L) {
// 为头结点分配内存
L = new LNode; // C++ 动态分配语法,若用纯 C 可写成 L = (LinkList)malloc(sizeof(LNode));
// 头结点的 next 指针置空,表示链表初始为空
L->next = NULL;
// 返回初始化成功状态
return OK;
}
#include <stdio.h>
int main() {
// 定义链表指针
LinkList L;
// 调用初始化函数
if (InitList_L(L) == OK) {
printf("单链表初始化成功!\n");
// 可进一步操作链表,比如插入数据等
// 这里简单打印头结点地址 & 头结点 next 状态
printf("头结点地址:%p\n", L);
printf("头结点 next 指针:%p\n", L->next);
} else {
printf("单链表初始化失败!\n");
}
return 0;
}
C
销毁链表
Status DestroyList_L(LinkList &L) {
// 销毁单链表 L,释放所有结点内存
LinkList p; // 定义指针 p,用来暂存要删除的结点
// L 是链表头指针,只要 L 不为空,就继续销毁
while (L != NULL) {
p = L; // 1. 用 p 记录当前头结点
L = L->next; // 2. 头指针后移,指向下一个结点
delete p; // 3. 释放当前结点内存
}
return OK;
}
C
清空链表
Status ClearList(LinkList &L) {
LinkList p, q; // p: 当前要删除的结点;q: 保存下一个结点的指针
p = L->next; // 1. p 指向第一个数据结点(头结点的 next)
while (p) { // 2. 只要 p 不为空(还有数据结点)
q = p->next; // 2.1 先用 q 保存 p 的下一个结点
delete p; // 2.2 释放当前结点 p 的内存
p = q; // 2.3 p 移动到下一个结点(q 保存的位置)
}
L->next = NULL; // 3. 头结点的 next 置空,链表变为空
return OK;
}
C
求链表表长,就是从首元结点开始,依次计数所有结点
// 状态码(若需要可定义,这里简化)
// typedef int Status;
// 链表结点结构
typedef struct LNode {
int data; // 数据域
struct LNode *next; // 指针域
} LNode;
// 链表类型(指向头结点的指针)
typedef LNode *LinkList;
// 求表长函数:返回数据结点的个数
int ListLength_L(LinkList L) {
LinkList p;
int i = 0; // 新增:定义并初始化计数器 i
p = L->next; // p 指向第一个数据结点(跳过 头结点)
while (p) { // 只要 p 不为空(还有数据结点)
i++; // 统计个数
p = p->next; // 移动到下一个数据结点
}
return i; // 返回数据结点总数
}
C
5.取单链表中第i个元素的内容
就是获取线性表L中的某个数据元素的内容,通过变量e返回
// 基础类型定义
typedef int Status;
typedef int ElemType;
#define OK 1
#define ERROR 0
// 链表结点结构
typedef struct LNode {
ElemType data;
struct LNode *next;
} LNode;
typedef LNode *LinkList;
// 按位查找函数(与图中逻辑一致)
Status GetElem_L(LinkList L, int i, ElemType &e) {
LNode *p = L->next;
int j = 1;
while (p && j < i) {
p = p->next;
j++;
}
if (!p || j > i) return ERROR;
e = p->data;
return OK;
}
C++
!p
:等价于 p == NULL
,即 “指针 p
为空”。
6.按值查找—就是根据指定数据获取该数据所在的位置(地址)
7.插入
将线性表L中第i个数据元素删除
9.单链表的头插法就是把元素插入在链表头部,也叫做前插法
(1)从一个空表开始、重复读入数据;
(2)生成新结点,将读入数据存放到新结点的数据域中
(3)从最后一个结点开始,依次将各结点插入到链表的前端
10.单链表的尾插法
元素插入在链表尾部,就是从一个空表L开始,将新结点逐个插入到链表的尾部,尾指针r指向链表的尾结点
初始时,r同L均指向头结点,每读入一个数据元素就申请一个新结点,将新结点插入尾及诶单后,r指向新结点。
#include <stdio.h>
#include <stdlib.h>
// 定义链表节点和链表类型
typedef struct Node {
int data;
struct Node* next;
} Node;
typedef Node* LinkList; // 将Node*重命名为LinkList类型
// 初始化链表(创建头节点)
LinkList initList() {
LinkList head = (LinkList)malloc(sizeof(Node));
if (!head) {
printf("内存分配失败\n");
exit(EXIT_FAILURE);
}
head->next = NULL; // 头节点的next置空,表示空链表
return head;
}
// 判断链表是否为空
int isEmpty(LinkList head) {
return head->next == NULL;
}
// 在链表尾部插入节点
void appendNode(LinkList head, int data) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->next = NULL;
Node* current = head;
while (current->next) current = current->next;
current->next = newNode;
}
// 打印链表
void printList(LinkList head) {
Node* current = head->next; // 从头节点的下一个开始遍历
while (current) {
printf("%d -> ", current->data);
current = current->next;
}
printf("NULL\n");
}
// 释放链表内存
void freeList(LinkList head) {
Node* current = head->next;
Node* next;
while (current) {
next = current->next;
free(current);
current = next;
}
free(head); // 释放头节点
}
int main() {
LinkList list = initList(); // 初始化链表
printf("链表是否为空: %s\n", isEmpty(list) ? "是" : "否");
// 添加节点
appendNode(list, 10);
appendNode(list, 20);
appendNode(list, 30);
printf("链表内容:");
printList(list); // 输出: 10 -> 20 -> 30 -> NULL
freeList(list); // 释放内存
return 0;
}
C