单链表详解
引言
单链表是一种基本的数据结构,广泛应用于各种编程场景中。它是由一系列节点组成的数据结构,每个节点包含数据部分和指向下一个节点的指针。单链表的优点在于它能够灵活地插入和删除节点,而不必像数组那样移动大量元素。
单链表的定义
节点结构
单链表中的每个节点通常由两部分组成:
- 数据部分:存储实际的数据项。
- 指针部分:存储指向下一个节点的地址。
节点的结构可以用 C 语言定义如下:
typedef struct ListNode {
int data; // 存储数据
struct ListNode *next; // 指向下一个节点的指针
} ListNode;
链表结构
单链表由一个头结点和一系列普通节点组成。头结点通常不存储数据,而是作为一个指向第一个数据节点的指针。
链表的结构可以用 C 语言定义如下:
ListNode *head; // 头结点
单链表的基本操作
初始化
初始化一个空的单链表包括分配一个头结点,并将其 next
指针设置为 NULL
。
bool InitList(ListNode *&head) {
head = (ListNode *)malloc(sizeof(ListNode));
if (head == NULL) {
return false; // 内存分配失败
}
head->next = NULL;
return true;
}
插入
插入操作可以发生在链表的任何位置,常见的有头部插入和尾部插入。
头部插入
void ListHeadInsert(ListNode *&head) {
int x;
ListNode *s;
printf("请输入加入单链表的值(输入-1结束):");
scanf("%d", &x);
while (x != -1) {
s = (ListNode *)malloc(sizeof(ListNode));
s->data = x;
s->next = head->next;
head->next = s;
scanf("%d", &x);
}
}
尾部插入
void ListTailInsert(ListNode *&head) {
int x;
ListNode *s, *r = head;
printf("请输入加入单链表的值(输入-1结束):");
scanf("%d", &x);
while (x != -1) {
s = (ListNode *)malloc(sizeof(ListNode));
s->data = x;
s->next = NULL;
r->next = s;
r = s;
scanf("%d", &x);
}
}
删除
删除操作可以从链表中移除一个节点。通常需要找到待删除节点的前一个节点。
bool ListDelete(ListNode *&head, int i, int &e) {
int j = 0;
ListNode *p = head, *q;
if (i <= 0) {
return false;
}
while (j < i - 1 && p != NULL) {
j++;
p = p->next;
}
if (p == NULL || p->next == NULL) {
return false;
}
q = p->next;
e = q->data;
p->next = q->next;
free(q);
return true;
}
查询
查询操作可以查找特定值或位置上的节点。
按值查询
int LocateElem(ListNode *head, int e) {
int i = 1;
ListNode *p = head->next;
while (p != NULL && p->data != e) {
p = p->next;
i++;
}
if (p == NULL) {
return 0;
} else {
return i;
}
}
按位置查询
int GetElem(ListNode *head, int i) {
int j = 0;
ListNode *p = head;
if (i <= 0) {
return -1;
}
while (j < i && p != NULL) {
j++;
p = p->next;
}
if (p == NULL) {
return -1;
} else {
return p->data;
}
}
打印输出
输出链表中的所有节点。
void DisplayList(ListNode *head) {
ListNode *p = head->next;
while (p != NULL) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
销毁
销毁整个链表。
void DestroyList(ListNode *&head) {
ListNode *p = head->next, *q;
while (p != NULL) {
q = p;
p = p->next;
free(q);
}
free(head);
}
示例程序
下面是一个使用上述定义和操作的完整单链表程序示例:
#include <stdio.h>
#include <stdlib.h>
typedef struct ListNode {
int data;
struct ListNode *next;
} ListNode;
bool InitList(ListNode *&head) {
head = (ListNode *)malloc(sizeof(ListNode));
if (head == NULL) {
return false;
}
head->next = NULL;
return true;
}
void ListHeadInsert(ListNode *&head) {
int x;
ListNode *s;
printf("请输入加入单链表的值(输入-1结束):");
scanf("%d", &x);
while (x != -1) {
s = (ListNode *)malloc(sizeof(ListNode));
s->data = x;
s->next = head->next;
head->next = s;
scanf("%d", &x);
}
}
void ListTailInsert(ListNode *&head) {
int x;
ListNode *s, *r = head;
printf("请输入加入单链表的值(输入-1结束):");
scanf("%d", &x);
while (x != -1) {
s = (ListNode *)malloc(sizeof(ListNode));
s->data = x;
s->next = NULL;
r->next = s;
r = s;
scanf("%d", &x);
}
}
bool ListDelete(ListNode *&head, int i, int &e) {
int j = 0;
ListNode *p = head, *q;
if (i <= 0) {
return false;
}
while (j < i - 1 && p != NULL) {
j++;
p = p->next;
}
if (p == NULL || p->next == NULL) {
return false;
}
q = p->next;
e = q->data;
p->next = q->next;
free(q);
return true;
}
int LocateElem(ListNode *head, int e) {
int i = 1;
ListNode *p = head->next;
while (p != NULL && p->data != e) {
p = p->next;
i++;
}
if (p == NULL) {
return 0;
} else {
return i;
}
}
int GetElem(ListNode *head, int i) {
int j = 0;
ListNode *p = head;
if (i <= 0) {
return -1;
}
while (j < i && p != NULL) {
j++;
p = p->next;
}
if (p == NULL) {
return -1;
} else {
return p->data;
}
}
void DisplayList(ListNode *head) {
ListNode *p = head->next;
while (p != NULL) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
void DestroyList(ListNode *&head) {
ListNode *p = head->next, *q;
while (p != NULL) {
q = p;
p = p->next;
free(q);
}
free(head);
}
int main() {
ListNode *head;
bool flagInsert = true;
if (InitList(head)) {
printf("单链表已初始化。\n");
}
ListHeadInsert(head);
printf("插入数据结束\n");
DisplayList(head);
bool flagDelete = true;
while (flagDelete) {
int i;
int e;
printf("请输入需要删除的位置(输入0退出):");
scanf("%d", &i);
if (i == 0) {
break;
}
flagDelete = ListDelete(head, i, e);
if (flagDelete) {
printf("删除数据成功,删除的数据为%d\n", e);
DisplayList(head);
} else {
printf("删除数据失败\n");
}
}
printf("删除数据结束\n");
int value;
printf("请输入需要按值查询的值:");
scanf("%d", &value);
int position = LocateElem(head, value);
if (position > 0) {
printf("查询成功,查询到的值为:%d\n", value);
} else {
printf("查询失败\n");
}
int wei;
printf("请输入需要按位查询的位置:");
scanf("%d", &wei);
int zhi = GetElem(head, wei);
if (zhi != -1) {
printf("查询成功,查询到的值为:%d\n", zhi);
} else {
printf("查询失败\n");
}
DestroyList(head);
printf("销毁单链表\n");
return 0;
}
以上就是单链表的详细介绍。希望这份文档能帮助您更好地理解和使用单链表。