详细介绍C语言中双向循环链表在数据结构中的实现和基本操作
目录
一、什么是双向循环链表
二、双向循环链表的特点
三、双向循环链表的优缺点
四、双向循环链表的应用场景
五、双向循环链表的常见操作
1、双向循环链表的定义和结构
2、创建双向循环链表头
3、判断链表是否为空
4、在双向循环链表中插入节点
5、从双向循环链表中删除节点
6、查找链表的元素或元素的下标
7、修改链表的元素
8、获取链表的长度
9、遍历双向循环链表
10、释放双向循环链表的内存
11、完整代码
数据结构是计算机科学中的核心概念之一。在开发和设计算法时,选择合适的数据结构对于程序的性能和可读性至关重要。双向循环链表是一种常用的数据结构,它允许在链表中进行前后遍历,并且可以很方便地插入和删除节点。本文将详细介绍双向循环链表的概念、特点以及常见操作的实现方法。
一、什么是双向循环链表?
双向循环链表是一种链表数据结构,它的节点包含两个指针:一个指向前一个节点,一个指向后一个节点。与单向链表不同的是,双向循环链表的最后一个节点的后继指针指向第一个节点,而第一个节点的前驱指针指向最后一个节点,形成一个循环的闭环。
二、双向循环链表的特点
双向遍历:由于每个节点都有前驱和后继指针,可以从任意一个节点出发,向前或向后遍历整个链表。
循环性质:最后一个节点的后继指针指向第一个节点,第一个节点的前驱指针指向最后一个节点,形成一个循环。
灵活插入和删除:相比于单向链表,双向循环链表的插入和删除操作更为灵活方便,不需要遍历整个链表来寻找特定位置。
三、双向循环链表的优缺点
优点:灵活插入和删除节点、双向遍历链表、循环性质使得某些问题更容易解决。
缺点:相对于单向链表,每个节点需要额外存储两个指针,占用更多的内存空间;修改和查询比较麻烦
四、双向循环链表的应用场景
缓存淘汰算法:例如LRU缓存算法中,使用双向循环链表来维护最近访问的数据。
图的遍历:在图的深度优先搜索和广度优先搜索中,可以使用双向循环链表作为辅助数据结构来存储已访问的节点。
五、双向循环链表的常见操作
1、双向循环链表的定义和结构
// 链表节点结构体
typedef struct Node {
typData data;// 节点数据
int tail;//记录节点数
struct Node *prev;//指向上一个节点的指针
struct Node *next;//指向下一个节点的指针
} Linklist, *Plinklist;
2、创建双向循环链表头
// 创建链表
Plinklist createLinkedList(Plinklist *list){
(*list) = (Plinklist)malloc(sizeof(Linklist));//为表头申请空间
if((*list) == NULL){
perror("createLinkedList list malloc");
}
(*list)->prev = *list;//头节点的上一个节点还是指向头节点
(*list)->next = *list;//头节点的下一个节点还是指向头节点
(*list)->tail = 1;//记录节点数,带头节点已经存在
return *list;
}
3、判断链表是否为空
// 判断链表是否为空
int isEmpty(Plinklist list){
if(list->next == list || list->tail == 0){
//puts("表是空的!");
return 1;//真空
}else{
return 0;//非空
}
}
4、在双向循环链表中插入节点
①头插法:在带头节点的后面插入
1、只有一个带头结点
2、不只带头结点
// 在链表头部插入元素
void insertAtHead(Plinklist list, typData value){
if(list == NULL){
puts("insert head arg err");
return ;
}
Plinklist newNode = (Plinklist)malloc(sizeof(Linklist));
if(newNode == NULL){
perror("insert head newNode malloc");//头插入内存分配失败
return ;
}
newNode->data = value;//设置新节点的数据值
if(list->next == list && list->prev == list){
newNode->next = list;
newNode->prev = list;
list->prev = newNode;
list->next = newNode;
}else{
newNode->next = list->next;
newNode->prev = list;
list->next->prev = newNode;
list->next = newNode;
}
list->tail++;//链表长度加一
}
②尾插法
// 在链表尾部插入元素
void insertAtTail(Plinklist list, typData value){
if(list == NULL){
puts("insert tail arg err");
return ;
}
Plinklist newNode = (Plinklist)malloc(sizeof(Linklist));
if(newNode == NULL){
perror("insert tail newNode malloc");
return ;
}
newNode->data = value;// 设置新节点的数据值
newNode->next = list;// 新节点的后继节点指向NULL
Plinklist current_tail = list;// 重新定义一个新指针指向头节点
while(current_tail->next != list){
current_tail = current_tail->next;// 遍历找到链表的尾节点
}
newNode->prev = current_tail;// 新节点的前驱节点指向尾节点
list->prev = newNode;
current_tail->next = newNode;// 尾节点的后继节点指向新节点
list->tail++;// 节点数加一
}
③在任意位置插入法
// 在指定位置插入元素
void insertAtPosition(Plinklist list, int position, typData value){
if(list ==NULL){
puts("insert position arg err");
return ;
}
if(position < 0 || position > (list->tail)){// 检查输入的position下标是否存在
puts("无效位置!");
return ;
}
Plinklist newNode = (Plinklist)malloc(sizeof(Linklist));//创建一个要插入的新节点
newNode->data = value;//设置新节点的数据值
Plinklist current = list;//重新定义一个新指针指向头节点
int count = 0;//定义一个计数变量
while(current->next != list && count < position){
current = current->next;// 找到要插入位置的前一个节点
count++;
}
newNode->next = current->next;// 新节点的后继指向要原删除节点的前一节点的下一个节点
newNode->prev = current;// 新节点的前驱指向新节点的前一节点
if (current->next != list) {
current->next->prev = newNode;// 更新原来节点和新节点的连接
}
current->next = newNode;// 将新界嗲连接到原节点之后
list->tail++;
}
5、从双向循环链表中删除节点
①删除头节点
// 删除头节点
void deleteHead(Plinklist list){
if(list ==NULL){
puts("dalete head arg err");
return ;
}
if(isEmpty(list)){
puts("表是空的!");
return ;
}
Plinklist deleteHead = list->next;// 定义一个新的删除指针指向头节点的下一个节点
list->next = deleteHead->next;// 头节点的后继更新为要删除节点的后一个后一个节点(也
可以是list>next = list->next->next)
if (deleteHead->next != list) {
deleteHead->next->prev = list;// 更新头节点和新节点的连接
}else{
list->next = list;
list->prev = list;
}
free(deleteHead);//释放删除节点的内存
list->tail--;// 节点数减一
}
②删除尾节点
// 删除尾节点
void deleteTail(Plinklist list){
if(list ==NULL){
puts("dalete tail arg err");
return ;
}
if(isEmpty(list)){
puts("表是空的!");
return ;
}
Plinklist current = list;
while(current->next != list){
current = current->next; 找到尾节点
}
//Plinklist deleteTail = current;
current->prev->next = list;// 要删除节点的上一个节点的后继直接连接NULL,断开要删除>节点和NULL的连接
list->prev = current->prev;
free(current);
list->tail--;// 节点数减一
}
③删除任意节点
// 删除指定位置的节点
void deleteAtPosition(Plinklist list, int position){
if (isEmpty(list)) {
printf("链表为空,删不了,根本删不了\n");
return ;
}
Plinklist current = list; // 从头节点开始遍历链表,找到要删除节点的前一个节点
int count = 0;
while (current->next != list && count < position) {
current = current->next;// 不断更新current指针
count++;
}
if (current->next == list || position < 0) {// 检查删除位置的有效性
printf("无效的删除位置\n");
return ;
}
Plinklist deletePosition = current->next;//定义新的指针记录要删除节点的上一个节点
current->next = deletePosition->next;// 要删除节点的上一个节点的后继连接到要删除节>点的后一个节点,断开要删除节点的和要删除节点的上一个节点的后继
if (deletePosition->next != list) {
deletePosition->next->prev = current;//更新前后节点的连接
}
free(deletePosition);//释放删除节点的内存
list->tail--;//节点数减一
if (isEmpty(list)) {
printf("链表为空,删不了了,根本删不了了\n");
return ;
}
}
6、查找链表的元素或元素的下标
①按值查找节点的下标位置
// 按值查找节点的位置
int findPositionByValue(Plinklist list, typData value){
if(list ==NULL){
puts("findValue Position arg err");
return -1;
}
if(isEmpty(list)){
puts("表是空的!");
return 1;
}
Plinklist current = list->next;
int position = 0;//定义下标从0开始
while (current != list) {
if (current->data == value) {
return position; // 找到节点的数据值等于目标值,返回节点的下标
}
current = current->next;
position++;
}
printf("没有该值!");
return -1; // 未找到目标值,返回false
}
②// 按下标查找节点的值
int findValueByPosition(Plinklist list, int position){
if(list ==NULL){
puts("findPosition Value arg err");
return -1;
}
if(isEmpty(list)){
puts("表是空的!");
return 1;
}
Plinklist current = list->next; // 从第一个节点开始遍历链表
int count = 0;
while (current != list && count < position) {
current = current->next;
count++;
}
if (current == list || position < 0 || position > (list->tail)) {// 检查下标的有效>性
printf("无效的下标\n");
return -1;
}
return current->data; // 返回找到的节点的数据值
}
7、修改链表的元素
①修改指定下标位置的节点值
// 修改指定位置的节点值
void modifyByPosition(Plinklist list, int position, typData value){
if(list ==NULL){
puts("modifyPosition Value arg err");
return ;
}
if (isEmpty(list)) {
printf("链表为空,无法修改元素\n");
return ;
}
Plinklist current = list->next; // 从第一个节点开始遍历链表
int count = 0;
while (current != list && count < position) {
current = current->next;
count++;
}
if (current == NULL || position < 0 || position > list->tail) {
printf("无效的下标\n");
return ;
}
current->data = value; // 修改节点的数据值
}
②修改指定值的节点值
// 修改指定值的节点值
void modifyValue(Plinklist list, typData oldValue, typData newValue){
if(list ==NULL){
puts("modifyValue Value arg err");
return ;
}
if (isEmpty(list)) {
printf("链表为空,无法修改节点值\n");
return ;
}
Plinklist current = list->next; // 从第一个节点开始遍历链表
while (current != list) {
if (current->data == oldValue) {
current->data = newValue; // 找到节点的数据值等于旧值,更新节点的数据值为新值
return ;
}
current = current->next;
}
printf("未找到目标值\n");
}
8、获取链表的长度
// 获取链表长度
int getLength(Plinklist list){
if(isEmpty(list)){
puts("链表为空!");
return 0;
}
return (list->tail) - 1;
//return list->tail;
}
9、遍历双向循环链表
①向前遍历(从带头结点的下一个节点开始遍历到尾节点)
//向前遍历链表并打印节点值(从头节点遍历到尾节点)
void next_traverse(Plinklist list){
if(list == NULL){
puts("next_traverse arg err");
return ;
}
if(isEmpty(list)){
puts("链表为空!");
return ;
}
Plinklist current = list->next;
while (current != list) {
printf("%d ", current->data);
current = current->next;
}
printf("\n");
}
②向后遍历(从尾节点遍历到带头结点的下一个节点)
//向后遍历链表并打印节点值(从尾节点遍历到头节点)
void prev_traverse(Plinklist list){
if(list == NULL){
puts("prev_traverse arg err");
return ;
}
if(isEmpty(list)){
puts("链表为空!");
return ;
}
Plinklist current_tail = list;
while(current_tail->next != list){
current_tail = current_tail->next;// 找到尾节点
}
Plinklist current = current_tail;
while(current != list){
printf("%d ",current->data);// 打印节点值
current = current->prev;
}
printf("\n");
}
10、释放双向循环链表的内存
同样我们调用删头函数或者删尾函数
// 清空链表
void clearList(Plinklist list){
while(list->next != list){
deleteHead(list);//调用删除头节点函数,实现不断的删除头节点
}
printf("表已被清空!\n");
return ;
}
11、完整代码
同样分三个文件来执行:①接口文件dlinklist.h ②接口实现文件dlinklist.c ③函数调用文件dlinklist_main.c
①接口文件dlinklist.h
#ifndef _BLINKLIST_H_
#define _BLINKLIST_H_
#include <stdio.h>
#include <stdlib.h>
typedef int typData;
// 链表节点结构体
typedef struct Node {
typData data;// 节点数据
int tail;//记录节点数
struct Node *prev;//指向下一个节点的指针
struct Node *next;//指向下一个节点的指针
} Linklist, *Plinklist;
// 创建链表
Plinklist createLinkedList(Plinklist *list);
// 判断链表是否为空
int isEmpty(Plinklist list);
// 在链表头部插入元素
void insertAtHead(Plinklist list, typData value);
// 在链表尾部插入元素
void insertAtTail(Plinklist list, typData value);
// 在指定位置插入元素
void insertAtPosition(Plinklist list, int position, typData value);
// 删除头节点
void deleteHead(Plinklist list);
// 删除尾节点
void deleteTail(Plinklist list);
// 删除指定位置的节点
void deleteAtPosition(Plinklist list, int position);
// 按值查找节点的位置
int findPositionByValue(Plinklist list, typData value);
// 按下标查找节点的值
int findValueByPosition(Plinklist list, int position);
// 修改指定位置的节点值
void modifyByPosition(Plinklist list, int position, typData value);
// 修改指定值的节点值
void modifyValue(Plinklist list, typData oidValue, typData newValue);
// 获取链表长度
int getLength(Plinklist list);
// 向前遍历链表并打印节点值
void prev_traverse(Plinklist list);
// 向后遍历链表并打印节点值
void next_traverse(Plinklist list);
// 清空链表
void clearList(Plinklist list);
#endif
②接口实现文件dlinklist.c
#include "dlinklist.h"
// 创建链表
Plinklist createLinkedList(Plinklist *list){
(*list) = (Plinklist)malloc(sizeof(Linklist));//为表头申请空间
if((*list) == NULL){
perror("createLinkedList list malloc");
}
(*list)->prev = *list;//头节点的上一个节点还是指向头节点
(*list)->next = *list;//头节点的下一个节点还是指向头节点
(*list)->tail = 1;//记录节点数
return *list;
}
// 判断链表是否为空
int isEmpty(Plinklist list){
if(list->next == list || list->tail == 0){
//puts("表是空的!");
return 1;//真空
}else{
return 0;//非空
}
}
// 在链表头部插入元素
void insertAtHead(Plinklist list, typData value){
if(list == NULL){
puts("insert head arg err");
return ;
}
Plinklist newNode = (Plinklist)malloc(sizeof(Linklist));
if(newNode == NULL){
perror("insert head newNode malloc");//头插入内存分配失败
return ;
}
newNode->data = value;//设置新节点的数据值
if(list->next == list && list->prev == list){
newNode->next = list;
newNode->prev = list;
list->prev = newNode;
list->next = newNode;
}else{
newNode->next = list->next;
newNode->prev = list;
list->next->prev = newNode;
list->next = newNode;
}
list->tail++;//链表长度加一
}
// 在链表尾部插入元素
void insertAtTail(Plinklist list, typData value){
if(list == NULL){
puts("insert tail arg err");
return ;
}
Plinklist newNode = (Plinklist)malloc(sizeof(Linklist));
if(newNode == NULL){
perror("insert tail newNode malloc");
return ;
}
newNode->data = value;// 设置新节点的数据值
newNode->next = list;// 新节点的后继节点指向NULL
Plinklist current_tail = list;// 重新定义一个新指针指向头节点
while(current_tail->next != list){
current_tail = current_tail->next;// 遍历找到链表的尾节点
}
newNode->prev = current_tail;// 新节点的前驱节点指向尾节点
list->prev = newNode;
current_tail->next = newNode;// 尾节点的后继节点指向新节点
list->tail++;// 节点数加一
}
// 在指定位置插入元素
void insertAtPosition(Plinklist list, int position, typData value){
if(list ==NULL){
puts("insert position arg err");
return ;
}
if(position < 0 || position > (list->tail)){// 检查输入的position下标是否存在
puts("无效位置!");
return ;
}
Plinklist newNode = (Plinklist)malloc(sizeof(Linklist));//创建一个要插入的新节点
newNode->data = value;//设置新节点的数据值
Plinklist current = list;//重新定义一个新指针指向头节点
int count = 0;//定义一个计数变量
while(current->next != list && count < position){
current = current->next;// 找到要插入位置的前一个节点
count++;
}
newNode->next = current->next;// 新节点的后继指向要原删除节点的前一节点的下一个节点
newNode->prev = current;// 新节点的前驱指向新节点的前一节点
if (current->next != list) {
current->next->prev = newNode;// 更新原来节点和新节点的连接
}
current->next = newNode;// 将新界嗲连接到原节点之后
list->tail++;
}
// 删除头节点
void deleteHead(Plinklist list){
if(list ==NULL){
puts("dalete head arg err");
return ;
}
if(isEmpty(list)){
puts("表是空的!");
return ;
}
Plinklist deleteHead = list->next;// 定义一个新的删除指针指向头节点的下一个节点
list->next = deleteHead->next;// 头节点的后继更新为要删除节点的后一个后一个节点(也可以是list>next = list->next->next)
if (deleteHead->next != list) {
deleteHead->next->prev = list;// 更新头节点和新节点的连接
}else{
list->next = list;
list->prev = list;
}
free(deleteHead);//释放删除节点的内存
list->tail--;// 节点数减一
}
// 删除尾节点
void deleteTail(Plinklist list){
if(list ==NULL){
puts("dalete tail arg err");
return ;
}
if(isEmpty(list)){
puts("表是空的!");
return ;
}
Plinklist current = list;
while(current->next != list){
current = current->next; 找到尾节点
}
//Plinklist deleteTail = current;
current->prev->next = list;// 要删除节点的上一个节点的后继直接连接NULL,断开要删除节点和NULL的连接
list->prev = current->prev;
free(current);
list->tail--;// 节点数减一
}
// 删除指定位置的节点
void deleteAtPosition(Plinklist list, int position){
if (isEmpty(list)) {
printf("链表为空,删不了,根本删不了\n");
return ;
}
Plinklist current = list; // 从头节点开始遍历链表,找到要删除节点的前一个节点
int count = 0;
while (current->next != list && count < position) {
current = current->next;// 不断更新current指针
count++;
}
if (current->next == list || position < 0) {// 检查删除位置的有效性
printf("无效的删除位置\n");
return ;
}
Plinklist deletePosition = current->next;//定义新的指针记录要删除节点的上一个节点
current->next = deletePosition->next;// 要删除节点的上一个节点的后继连接到要删除节点的后一个节点,断开要删除节点的和要删除节点的上一个节
点的后继
if (deletePosition->next != list) {
deletePosition->next->prev = current;//更新前后节点的连接
}
free(deletePosition);//释放删除节点的内存
list->tail--;//节点数减一
if (isEmpty(list)) {
printf("链表为空,删不了了,根本删不了了\n");
return ;
}
}
// 按值查找节点的位置
int findPositionByValue(Plinklist list, typData value){
if(list ==NULL){
puts("findValue Position arg err");
return -1;
}
if(isEmpty(list)){
puts("表是空的!");
return 1;
}
Plinklist current = list->next;
int position = 0;//定义下标从0开始
while (current != list) {
if (current->data == value) {
return position; // 找到节点的数据值等于目标值,返回节点的下标
}
current = current->next;
position++;
}
printf("没有该值!");
return -1; // 未找到目标值,返回false
}
// 按下标查找节点的值
int findValueByPosition(Plinklist list, int position){
if(list ==NULL){
puts("findPosition Value arg err");
return -1;
}
if(isEmpty(list)){
puts("表是空的!");
return 1;
}
Plinklist current = list->next; // 从第一个节点开始遍历链表
int count = 0;
while (current != list && count < position) {
current = current->next;
count++;
}
if (current == list || position < 0 || position > (list->tail)) {// 检查下标的有效性
printf("无效的下标\n");
return -1;
}
return current->data; // 返回找到的节点的数据值
}
// 修改指定位置的节点值
void modifyByPosition(Plinklist list, int position, typData value){
if(list ==NULL){
puts("modifyPosition Value arg err");
return ;
}
if (isEmpty(list)) {
printf("链表为空,无法修改元素\n");
return ;
}
Plinklist current = list->next; // 从第一个节点开始遍历链表
int count = 0;
while (current != list && count < position) {
current = current->next;
count++;
}
if (current == NULL || position < 0 || position > list->tail) {
printf("无效的下标\n");
return ;
}
current->data = value; // 修改节点的数据值
}
// 修改指定值的节点值
void modifyValue(Plinklist list, typData oldValue, typData newValue){
if(list ==NULL){
puts("modifyValue Value arg err");
return ;
}
if (isEmpty(list)) {
printf("链表为空,无法修改节点值\n");
return ;
}
Plinklist current = list->next; // 从第一个节点开始遍历链表
while (current != list) {
if (current->data == oldValue) {
current->data = newValue; // 找到节点的数据值等于旧值,更新节点的数据值为新值
return ;
}
current = current->next;
}
printf("未找到目标值\n");
}
// 获取链表长度
int getLength(Plinklist list){
if(isEmpty(list)){
puts("链表为空!");
return 0;
}
return (list->tail) - 1;
//return list->tail;
}
//向后遍历链表并打印节点值(从尾节点遍历到头节点)
void prev_traverse(Plinklist list){
if(list == NULL){
puts("prev_traverse arg err");
return ;
}
if(isEmpty(list)){
puts("链表为空!");
return ;
}
Plinklist current_tail = list;
while (current != list) {
printf("%d ", current->data);
current = current->next;
}
printf("\n");
}
// 清空链表
void clearList(Plinklist list){
while(list->next != list){
deleteHead(list);//调用删除头节点函数,实现不断的删除头节点
}
printf("表已被清空!\n");
return ;
}
③函数调用文件dlinklist_main.c
int main() {
Plinklist list;
createLinkedList(&list);
int choice, value, position, oldValue, newValue;
while (1) {
printf("\n*****************************链表操作菜单*****************************\n");
printf("1. 在头部插入元素 2. 在尾部插入元素 3. 在任意位置插入元素\n");
printf("4. 删除头节点 5. 删除尾节点 6. 删除任意位置的节点\n");
printf("7. 按值查找元素的位置 8. 按位置查找元素的值 9. 修改指定位置的节点值\n");
printf("10. 修改指定值的节点值 11. 获取链表长度 12. 遍历链表\n");
printf("13. 清空链表 14. 退出程序\n");
printf("*********************************************************************\n");
printf("请输入操作编号:");
scanf("%d", &choice);
char input[10];
switch (choice) {
case 1:
while(1){
printf("请输入要插入的元素值(按q结束元素输入)):");
scanf("%s", input);
if (strcmp(input, "q") == 0) {
break; // 退出循环
}
value = atoi(input); // 将字符串转换为整数
//scanf("%d", &value);
insertAtHead(list, value);
printf("向后遍历:");
prev_traverse(list);
printf("向前遍历:");
next_traverse(list);
}
break;
case 2:
while(1){
printf("请输入要插入的元素值(按q结束元素输入)):");
scanf("%s", input);
if (strcmp(input, "q") == 0) {
break; // 退出循环
}
value = atoi(input); // 将字符串转换为整数
//printf("请输入要插入的元素值:");
//scanf("%d", &value);
insertAtTail(list, value);
printf("向后遍历:");
prev_traverse(list);
printf("向前遍历:");
next_traverse(list);
}
break;
case 3:
while(1){
printf("请输入要插入的位置(按q结束元素输入):");
scanf("%s", input);
if (strcmp(input, "q") == 0) {
break; // 退出循环
}
position = atoi(input); // 将字符串转换为整数
//scanf("%d", &position);
printf("请输入要插入的元素值:");
scanf("%d", &value);
insertAtPosition(list, position, value);
printf("向后遍历:");
prev_traverse(list);
printf("向前遍历:");
next_traverse(list);
}
break;
case 4:
deleteHead(list);
printf("向后遍历:");
prev_traverse(list);
printf("向前遍历:");
next_traverse(list);
break;
case 5:
deleteTail(list);
printf("向后遍历:");
prev_traverse(list);
printf("向前遍历:");
next_traverse(list);
break;
case 6:
printf("请输入要删除的位置:");
scanf("%d", &position);
deleteAtPosition(list, position);
printf("向后遍历:");
prev_traverse(list);
printf("向前遍历:");
next_traverse(list);
break;
case 7:
printf("请输入要查找的元素值:");
scanf("%d", &value);
position = findPositionByValue(list, value);
if (position != -1) {
printf("元素值 %d 的位置是:%d\n", value, position);
}
break;
case 8:
printf("请输入要查找的位置:");
scanf("%d", &position);
value = findValueByPosition(list, position);
if(!(position < 0 || position > (list->tail))){
printf("位置 %d 上的元素值是:%d\n", position, value);
}
break;
case 9:
printf("请输入要修改的位置:");
scanf("%d", &position);
printf("请输入修改后的元素值:");
scanf("%d", &value);
modifyByPosition(list, position, value);
printf("向后遍历:");
prev_traverse(list);
printf("向前遍历:");
next_traverse(list);
break;
case 10:
printf("请输入要修改的元素值:");
scanf("%d", &oldValue);
printf("请输入修改后的元素值:");
scanf("%d", &newValue);
modifyValue(list, oldValue, newValue);
printf("向后遍历:");
prev_traverse(list);
printf("向前遍历:");
next_traverse(list);
break;
case 11:
printf("链表的长度是:%d\n", getLength(list));
break;
case 12:
printf("向后遍历:");
prev_traverse(list);
printf("向前遍历:");
next_traverse(list);
break;
case 13:
clearList(list);
break;
case 14:
printf("已退出!!\n");
exit(0);
default:
printf("无效的操作编号!\n");
break;
}
}
return 0;
}