赞
踩
链表是一种常用的数据结构,它由一系列节点组成,每个节点包含两部分内容:数据和指向下一个节点的指针,最后一个节点指向空。链表的节点可以动态添加和删除,因此可以方便地进行插入、删除等操作。链表有多种类型,包括单向链表、双向链表和循环链表等。
单向链表是最简单的链表类型,它的每个节点只包含一个指向下一个节点的指针。单向链表的优点是插入和删除节点的速度较快,但查找节点的速度较慢。单向链表的数据结构如下所示:
cstruct ListNode {
int val; // 节点的值
struct ListNode *next; // 指向下一个节点的指针
};
双向链表是在单向链表的基础上增加了一个指向前一个节点的指针。这样一来,双向链表可以从前往后遍历,也可以从后往前遍历,但相应地,插入和删除节点的操作会稍微复杂一些。双向链表的数据结构如下所示:
cstruct ListNode {
int val; // 节点的值
struct ListNode *prev; // 指向前一个节点的指针
struct ListNode *next; // 指向下一个节点的指针
};
循环链表是一种特殊的链表类型,它的最后一个节点指向第一个节点(或者说,第一个节点指向最后一个节点)。这样一来,循环链表可以无限循环下去,因此常用于循环队列等数据结构中。循环链表的数据结构和单向链表或双向链表类似,只是最后一个节点的指针指向第一个节点。
本教程主要演示的是单向链表的使用。
首先,我们需要定义链表的节点结构。每个节点包含一个数据元素和一个指向下一个节点的指针。在C语言中,我们可以使用结构体来定义节点。
typedef struct Node {
int data; // 数据元素
struct Node* next; // 指向下一个节点的指针
} Node;
下面是一个函数,用于创建并初始化一个空链表。
Node* createLinkedList() {
return NULL; // 返回空链表
}
接下来,我们需要实现在链表中插入新节点的功能。我们可以根据需要在链表的开头、末尾或中间插入新节点。
// 插入节点到链表开头 Node *insertAtBeginning(Node *head, int data) { // 创建新节点 Node *newNode = (Node*)malloc(sizeof(Node)); // 设置节点数据 newNode->data = data; // 将新节点指向原来的头节点 newNode->next = head; // 返回新的链表头节点 return newNode; } // 插入节点到链表末尾 Node *insertAtEnd(Node *head, int data) { // 创建新节点 Node *newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; // 将新节点的下一个节点指针设置为NULL newNode->next = NULL; // 如果链表为空,将新节点作为链表的唯一节点 if (head == NULL) { return newNode; } Node* current = head; // 遍历链表直到达到最后一个节点 while (current->next != NULL) { current = current->next; } // 将新节点插入到已有链表的末尾 current->next = newNode; // 返回原来的头节点 return head; } // 在指定位置插入节点 Node* insertAtPosition(Node* head, int data, int position) { // 创建新节点 Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; // 如果插入位置为0,则将新节点作为新的头节点 if (position == 0) { newNode->next = head; return newNode; } Node* current = head; // 找到插入位置的前一个节点 for (int i = 0; i < position - 1; i++) { if (current == NULL) { printf("位置超出链表存储范围。\n"); return head; } current = current->next; } // 将新节点的next指针指向当前位置的节点 newNode->next = current->next; // 将当前位置的节点指向新节点 current->next = newNode; // 返回原来的头节点 return head; }
我们也可以从链表中删除节点。下面是一些用于删除节点的函数示例。
// 从链表开头删除节点 Node* deleteAtBeginning(Node* head) { if (head == NULL) { printf("链表为空"); return NULL; } Node* temp = head; // 更新头节点 head = head->next; // 释放删除节点的内存 free(temp); // 返回新的头节点 return head; } // 从链表末尾删除节点 Node* deleteAtEnd(Node* head) { if (head == NULL) { printf("链表为空!!!\n"); return NULL; } // 如果只有一个节点,直接删除 if (head->next == NULL) { free(head); return NULL; } Node *current = head, *prev; // 找到倒数第二个节点 while (current->next != NULL) { prev = current; current = current->next; } //将倒数第二个节点的next指针设置为NULL,删除最后一个节点 prev->next = NULL; // 释放删除节点的内存 free(current); // 返回原来的头节点 return head; } // 根据数据值删除节点 Node* deleteByValue(Node* head, int data) { if (head == NULL) { printf("链表为空!!!\n"); return NULL; } Node *current = head, *prev; // 遍历链表找到要删除的节点 while (current != NULL && current->data != data) { prev = current; current = current->next; } if (current == NULL) { printf("数据不存在!!!\n"); return head; } if (current == head) { //如果删除节点是头节点,则更新头节点 head = head->next; } else { //将前一个节点的next指针跳过删除节点 prev->next = current->next; } free(current);// 释放删除节点的内存 return head; }
为了验证链表的操作,我们可以编写一个函数来打印链表的所有节点。
//打印链表数据
void printList(Node* head) {
Node* current = head;
printf("链表所存数据: ");
//表头为空,结束循环
while (current != NULL) {
printf("%d ", current->data);
current = current->next;
}
printf("\n");
}
我们可以编写一段测试代码来验证我们的链表代码:
//主函数 int main() { //创建链表 Node* head = createLinkedList(); printf("链表已经创建完成,可以正常使用!!!\n"); while(true){ printf("1、添加新的数据到链表头。\n"); printf("2、添加新的数据到链表尾。\n"); printf("3、添加新的数据到固定位置。\n"); printf("4、删除链表头的数据。\n"); printf("5、删除链表尾的数据。\n"); printf("6、删除指定数据。\n"); printf("7、退出程序。\n"); printf("请输入你的选择:"); int ch; bool flag=false; scanf("%d",&ch); system("cls"); switch(ch){ case 1: int insertN; printf("请输入需要插入的数据:"); scanf("%d",&insertN); head = insertAtBeginning(head, insertN); break; case 2: int insertEndN; printf("请输入需要插入的数据:"); scanf("%d",&insertEndN); head = insertAtEnd(head, insertEndN); break; case 3: int insertPosN,pos; printf("请输入需要插入的数据和位置:"); scanf("%d %d",&insertPosN,&pos); head = insertAtPosition(head, insertPosN, pos-1); break; case 4: head = deleteAtBeginning(head); break; case 5: head = deleteAtEnd(head); break; case 6: int delN; printf("请输入需要删除的数据:"); scanf("%d",&delN); head = deleteByValue(head, delN); break; case 7:printf("程序结束,欢迎使用。\n");exit(0); default: printf("您的输入有误,请检查后重新输入!\n"); flag=true; break; } if(!flag){ printf("****-----------------------------****\n"); printList(head); printf("****-----------------------------****\n\n"); } getchar(); } return 0; }
恭喜你!你已经完成了C语言实现链表的教程。链表是一种非常有用的数据结构,可以在运行时动态管理数据。通过学习链表的实现,您可以对如何操作和管理数据有更深入的了解。希望本教程对你有所帮助,谢谢!
#include <stdio.h> #include <stdlib.h> typedef struct Node { int data; // 数据元素 struct Node *next; // 指向下一个节点的指针 } Node; //创建并初始化链表 Node *createLinkedList() { return NULL; // 返回空链表 } // 插入节点到链表开头 Node *insertAtBeginning(Node *head, int data) { // 创建新节点 Node *newNode = (Node*)malloc(sizeof(Node)); // 设置节点数据 newNode->data = data; // 将新节点指向原来的头节点 newNode->next = head; // 返回新的链表头节点 return newNode; } // 插入节点到链表末尾 Node *insertAtEnd(Node *head, int data) { // 创建新节点 Node *newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; // 将新节点的下一个节点指针设置为NULL newNode->next = NULL; // 如果链表为空,将新节点作为链表的唯一节点 if (head == NULL) { return newNode; } Node* current = head; // 遍历链表直到达到最后一个节点 while (current->next != NULL) { current = current->next; } // 将新节点插入到已有链表的末尾 current->next = newNode; // 返回原来的头节点 return head; } // 在指定位置插入节点 Node* insertAtPosition(Node* head, int data, int position) { // 创建新节点 Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; // 如果插入位置为0,则将新节点作为新的头节点 if (position == 0) { newNode->next = head; return newNode; } Node* current = head; // 找到插入位置的前一个节点 for (int i = 0; i < position - 1; i++) { if (current == NULL) { printf("位置超出链表存储范围。\n"); return head; } current = current->next; } // 将新节点的next指针指向当前位置的节点 newNode->next = current->next; // 将当前位置的节点指向新节点 current->next = newNode; // 返回原来的头节点 return head; } // 从链表开头删除节点 Node* deleteAtBeginning(Node* head) { if (head == NULL) { printf("链表为空"); return NULL; } Node* temp = head; // 更新头节点 head = head->next; // 释放删除节点的内存 free(temp); // 返回新的头节点 return head; } // 从链表末尾删除节点 Node* deleteAtEnd(Node* head) { if (head == NULL) { printf("链表为空!!!\n"); return NULL; } // 如果只有一个节点,直接删除 if (head->next == NULL) { free(head); return NULL; } Node *current = head, *prev; // 找到倒数第二个节点 while (current->next != NULL) { prev = current; current = current->next; } //将倒数第二个节点的next指针设置为NULL,删除最后一个节点 prev->next = NULL; // 释放删除节点的内存 free(current); // 返回原来的头节点 return head; } // 根据数据值删除节点 Node* deleteByValue(Node* head, int data) { if (head == NULL) { printf("链表为空!!!\n"); return NULL; } Node *current = head, *prev; // 遍历链表找到要删除的节点 while (current != NULL && current->data != data) { prev = current; current = current->next; } if (current == NULL) { printf("数据不存在!!!\n"); return head; } if (current == head) { //如果删除节点是头节点,则更新头节点 head = head->next; } else { //将前一个节点的next指针跳过删除节点 prev->next = current->next; } free(current);// 释放删除节点的内存 return head; } //打印链表数据 void printList(Node* head) { Node* current = head; printf("链表所存数据: "); //表头为空,结束循环 while (current != NULL) { printf("%d ", current->data); current = current->next; } printf("\n"); } //主函数 int main() { //创建链表 Node* head = createLinkedList(); printf("链表已经创建完成,可以正常使用!!!\n"); while(true){ printf("1、添加新的数据到链表头。\n"); printf("2、添加新的数据到链表尾。\n"); printf("3、添加新的数据到固定位置。\n"); printf("4、删除链表头的数据。\n"); printf("5、删除链表尾的数据。\n"); printf("6、删除指定数据。\n"); printf("7、退出程序。\n"); printf("请输入你的选择:"); int ch; bool flag=false; scanf("%d",&ch); system("cls"); switch(ch){ case 1: int insertN; printf("请输入需要插入的数据:"); scanf("%d",&insertN); head = insertAtBeginning(head, insertN); break; case 2: int insertEndN; printf("请输入需要插入的数据:"); scanf("%d",&insertEndN); head = insertAtEnd(head, insertEndN); break; case 3: int insertPosN,pos; printf("请输入需要插入的数据和位置:"); scanf("%d %d",&insertPosN,&pos); head = insertAtPosition(head, insertPosN, pos-1); break; case 4: head = deleteAtBeginning(head); break; case 5: head = deleteAtEnd(head); break; case 6: int delN; printf("请输入需要删除的数据:"); scanf("%d",&delN); head = deleteByValue(head, delN); break; case 7:printf("程序结束,欢迎使用。\n");exit(0); default: printf("您的输入有误,请检查后重新输入!\n"); flag=true; break; } if(!flag){ printf("****-----------------------------****\n"); printList(head); printf("****-----------------------------****\n\n"); } getchar(); } return 0; }
以上就是C语言实现链表的详细教程。希望对您有所帮助!如果您还有其他问题,请随时提问。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。