带头节点链表基础操作,简单详细(附源码)
本篇面向的是初学者,旨在帮助他们了解数据结构中的带头结点的链表。
提供详细的过程的同时附源码,也是为了让自己的进步,共勉之。
前言
链表是一种常见的数据结构,它由节点组成,每个节点包含数据和指向 下一个节点 的指针。链表的灵活性使其在编程中应用广泛,本文将介绍如何使用C++实现链表,并提供一些链表操作的示例代码。
链表结构定义
首先,我们需要定义链表的节点结构。在这个示例中,我们使用以下结构来表示链表节点:
typedef struct ListNode {
int data;//值
struct ListNode* next; //指向下一个
} ListNode, *LinkedList;
这里的ListNode
结构包含一个整数数据成员 data
和一个指向下一个节点的指针 next
。同时,我们使用 LinkedList
类型来表示整个链表,它是一个指向 链表头节点的指针 。
初始化链表
接下来,我们需要初始化链表。下面是一个初始化链表的函数 `initLinkedList`:
LinkedList initLinkedList(LinkedList& head, int numElements) {
head = (LinkedList)malloc(sizeof(ListNode)); // 分配头节点的内存
head->next = NULL;
LinkedList tail = head;
int element;
while (numElements--) {
LinkedList new_node;
printf("请输入一个整数:");
scanf("%d", &element);
new_node = (LinkedList)malloc(sizeof(ListNode)); // 分配新节点的内存
new_node->data = element;
new_node->next = tail->next;//为新节点的next 赋NULL
tail->next = new_node;// 将新节点添加到链表尾部
tail = new_node;//指向末尾
}
return head;
}
此函数会初始化一个包含指定数量元素的链表。首先,它分配头节点的内存,并将头节点的 next
指针置为 NULL
。然后,它循环读取用户输入的整数,并将它们插入到链表的尾部。
插入元素
链表的一个常见操作是在指定位置前或后插入元素。
我们提供了两个函数 `insertBefore` 和 `insertAfter` 来执行这两种操作:
插入元素在指定位置前:
void insertBefore(LinkedList& head, int value, int position) {
LinkedList previous = head;
while (--position && previous) {//找到要插入位置的前一个节点 注意头节点不存值
previous = previous->next;
}
if (previous == NULL) {
cout << "无效位置";
return;
}
LinkedList new_node;
new_node = (LinkedList)malloc(sizeof(ListNode));
new_node->data = value;
new_node->next = previous->next;
previous->next = new_node;
}
插入元素在指定位置后:
void insertAfter(LinkedList& head, int value, int position) {
LinkedList current = head;
while (position && current) {
current = current->next;
position--;
}
if (current == NULL) {
cout << "无效位置";
return;
}
LinkedList new_node;
new_node = (LinkedList)malloc(sizeof(ListNode)); // 分配新节点的内存
new_node->next = current->next;
current->next = new_node; // 插入新节点
new_node->data = value;//插入要插入的值
}
这两个函数分别在指定位置前和后插入一个新节点,注意头节点不存储数据。
删除元素
我们也提供了一个函数 `deleteNode` 来删除链表中指定位置的元素:
void deleteNode(LinkedList& head, int position) {
LinkedList previous = head;
while (--position && previous) {
previous = previous->next;
}
if (previous == NULL) {
cout << "无效位置";
return;
}
LinkedList toDelete = previous->next;
previous->next = toDelete->next;
free(toDelete); // 释放被删除节点的内存
}
这个函数会删除指定位置的节点,并释放其内存。别忘了释放内存
计算链表长度
要计算链表的长度,我们可以使用 `getLength` 函数:
int getLength(LinkedList head) {
int length = 0;
LinkedList current = head;
while (current->next != NULL) {
current = current->next;
length++;
}
return length;
}
这个函数从链表头节点开始遍历链表,统计节点数量。
显示链表元素
要显示链表的元素,我们可以使用 `displayLinkedList` 函数:
void displayLinkedList(LinkedList head) {
LinkedList current = head->next;//头节点不赋值
printf("链表内容:\n");
while (current) {
printf("%d\n", current->data);
current = current->next;
}
}
这个函数从链表头节点开始遍历链表,依次打印出每个节点的数据。
main()代码
在 `main` 函数中,我们使用上述函数演示了如何初始化链表,插入和删除元素,以及计算链表的长度。最后,我们释放了链表节点的内存。
int main() {
LinkedList head;
int numElements;
printf("请输入元素数量:");
scanf("%d", &numElements);
initLinkedList(head, numElements);
displayLinkedList(head);
int value, position;
printf("请输入要在指定位置前插入的值和位置:");
scanf("%d %d", &value, &position);
insertBefore(head, value, position);
displayLinkedList(head);
printf("请输入要在指定位置后插入的值和位置:");
scanf("%d %d", &value, &position);
insertAfter(head, value, position);
displayLinkedList(head);
printf("请输入要删除的位置:");
scanf("%d", &position);
deleteNode(head, position);
displayLinkedList(head);
cout << "链表长度: " << getLength(head);
// 释放链表节点内存
LinkedList current = head->next;
while (current) {
LinkedList temp = current;
current = current->next;
free(temp);
}
free(head);
return 0;
}
完整代码:
#include <bits/stdc++.h>
#include <stdio.h>
using namespace std;
// 定义链表节点结构
typedef struct ListNode {
int data;
struct ListNode* next;
} ListNode, *LinkedList;
// 初始化链表
LinkedList initLinkedList(LinkedList& head, int numElements) {
head = (LinkedList)malloc(sizeof(ListNode)); // 分配头节点的内存
head->next = NULL;
LinkedList tail = head;
int element;
while (numElements--) {
LinkedList new_node;
printf("请输入一个整数:");
scanf("%d", &element);
new_node = (LinkedList)malloc(sizeof(ListNode)); // 分配新节点的内存
new_node->data = element;
new_node->next = tail->next;//为新节点的next置为NULL
tail->next = new_node; // 将新节点添加到链表尾部
tail = new_node;
}
return head;
}
// 显示链表元素
void displayLinkedList(LinkedList head) {
LinkedList current = head->next;
printf("链表内容:\n");
while (current) {
printf("%d\n", current->data);
current = current->next;
}
}
// 在指定位置前插入元素
void insertBefore(LinkedList& head, int value, int position) {
LinkedList previous = head;
while (--position && previous) {//找到要插入位置的前一个节点 注意头节点不存值
previous = previous->next;
}
if (previous == NULL) {
cout << "无效位置";
return;
}
LinkedList new_node;
new_node = (LinkedList)malloc(sizeof(ListNode)); // 分配新节点的内存
new_node->data = value;
new_node->next = previous->next;
previous->next = new_node; // 插入新节点
}
// 在指定位置后插入元素
void insertAfter(LinkedList& head, int value, int position) {
LinkedList current = head;
while (position && current) { //找的指定位置
current = current->next;
position--;
}
if (current == NULL) {
cout << "无效位置";
return;
}
LinkedList new_node;
new_node = (LinkedList)malloc(sizeof(ListNode)); // 分配新节点的内存
new_node->next = current->next;
current->next = new_node; // 插入新节点
new_node->data = value;
}
// 删除指定位置的元素
void deleteNode(LinkedList& head, int position) {
LinkedList previous = head;
while (--position && previous) {
previous = previous->next;
}
if (previous == NULL) {
cout << "无效位置";
return;
}
LinkedList toDelete = previous->next;
previous->next = toDelete->next;
free(toDelete); // 释放被删除节点的内存
}
// 计算链表的长度
int getLength(LinkedList head) {
int length = 0;
LinkedList current = head;
while (current->next != NULL) {
current = current->next;
length++;
}
return length;
}
int main() {
LinkedList head;
int numElements;
printf("请输入元素数量:");
scanf("%d", &numElements);
initLinkedList(head, numElements);
displayLinkedList(head);
int value, position;
printf("请输入要在指定位置前插入的值和位置:");
scanf("%d %d", &value, &position);
insertBefore(head, value, position);
displayLinkedList(head);
printf("请输入要在指定位置后插入的值和位置:");
scanf("%d %d", &value, &position);
insertAfter(head, value, position);
displayLinkedList(head);
printf("请输入要删除的位置:");
scanf("%d", &position);
deleteNode(head, position);
displayLinkedList(head);
cout << "链表长度: " << getLength(head);
// 释放链表节点内存
LinkedList current = head->next;
while (current) {
LinkedList temp = current;
current = current->next;
free(temp);
}
free(head);
return 0;
}
结语
这篇博客介绍了如何使用C++实现链表以及一些常见的链表操作。链表是一个重要的数据结构,它在编程中经常用于解决各种问题。希望这些示例代码能够帮助你更好地理解链表的工作原理和应用。