C语言双向链表如何实现向指定索引位置插入元素

核心代码:

int insertDoubleLinkedList(DoubleLinkedList *list, int index, int value) {
    if (list == NULL || list->head == NULL || list->tail == NULL) {
        return -1;
    }
    // 当一个元素都没有的时候,或者index=size的时候,是支持插入的
    if (index < 0 || index > list->size) {
        return -1;
    }
    // 创建节点
    DoubleLinkedListNode *newNode = newDoubleLinkedListNode(value);

    // 元素个数增加
    list->size++;

    // 插入到头部
    if (index == 0) {
        DoubleLinkedListNode *oldNode = list->head->next;
        list->head->next = newNode;
        newNode->prev = list->head;
        newNode->next = oldNode;
        oldNode->prev = newNode;
        return 0;
    }

    // 插入到尾部
    if (index == list->size) {
        DoubleLinkedListNode *oldNode = list->tail->prev;
        oldNode->next = newNode;
        newNode->prev = oldNode;
        newNode->next = list->tail;
        list->tail->prev = newNode;
        return list->size;
    }

    // 插入到中间
    int i = 0;
    DoubleLinkedListNode *current = list->head->next;
    while (i < index) {
        i++;
        current = current->next;
    }

    // 此时,current就是索引位置的节点,将该节点往后移动
    DoubleLinkedListNode *oldPrev = current->prev;
    oldPrev->next = newNode;
    newNode->prev = oldPrev;
    newNode->next = current;
    current->prev = newNode;

    // 返回
    return index;
}

double_linked_list.h

#ifndef ZDPC_ALGORITHM_DEV_DOUBLE_LINKED_LIST_H
#define ZDPC_ALGORITHM_DEV_DOUBLE_LINKED_LIST_H

// 公共头文件
#include "stdio.h"
#include "string.h"
#include "stdlib.h"

// 双向链表的节点
typedef struct doubleLinkedListNode {
    int data;
    struct doubleLinkedListNode *next; // 下一个节点
    struct doubleLinkedListNode *prev; // 上一个节点
} DoubleLinkedListNode;

// 双向链表
typedef struct doubleLinkedList {
    DoubleLinkedListNode *head; // 头节点
    DoubleLinkedListNode *tail; // 尾节点
    int size; // 节点的个数
} DoubleLinkedList;

extern DoubleLinkedList *newDoubleLinkedList(); // 创建双向链表
extern void freeDoubleLinkedList(DoubleLinkedList *list); // 释放双向链表内存
extern int isEmptyDoubleLinkedList(DoubleLinkedList *list); // 判断是否为空链表
extern int sizeDoubleLinkedList(DoubleLinkedList *list); // 获取链表的元素个数
extern void printDoubleLinkedList(DoubleLinkedList *list); // 打印链表的内容
extern void appendDoubleLinkedList(DoubleLinkedList *list, int value); // 将元素添加到链表末尾
extern int removeDoubleLinkedList(DoubleLinkedList *list, int value); // 从链表中移除元素,成功返回其索引,失败返回-1
extern int insertDoubleLinkedList(DoubleLinkedList *list, int index, int value); // 将数据插入到链表指定索引位置,成功返回其索引,失败返回-1

#endif //ZDPC_ALGORITHM_DEV_DOUBLE_LINKED_LIST_H

double_linked_list.c

#include "double_linked_list.h"

// 创建头节点
DoubleLinkedListNode *newDoubleLinkedListNode(int value) {
    // 申请节点的空间
    DoubleLinkedListNode *node = malloc(sizeof(DoubleLinkedListNode));

    // 初始化
    node->next = NULL;
    node->prev = NULL;
    node->data = value;

    // 返回
    return node;
}

// 创建双向链表
DoubleLinkedList *newDoubleLinkedList() {
    // 申请链表的内存
    DoubleLinkedList *list = malloc(sizeof(DoubleLinkedList));

    // 头节点
    DoubleLinkedListNode *head = newDoubleLinkedListNode(0);

    // 尾结点
    DoubleLinkedListNode *tail = newDoubleLinkedListNode(0);

    // 初始化
    list->head = head;
    list->tail = tail;
    list->size = 0;

    // 关系
    list->head->next = list->tail;
    list->tail->prev = list->head;

    // 返回
    return list;
}

// 释放双向链表内存
void freeDoubleLinkedList(DoubleLinkedList *list) {
    // 释放节点内存
    DoubleLinkedListNode *node = list->head->next;
    while (node->next != list->tail) {
        DoubleLinkedListNode *next = node->next;
        free(node);
        node = next;
    }
    // 释放首尾节点的内存
    free(list->head);
    free(list->tail);
    // 释放链表内存
    free(list);
}

// 判断是否为空链表
int isEmptyDoubleLinkedList(DoubleLinkedList *list) {
    return list != NULL && list->head->next == list->tail;
}

// 获取链表的元素个数
int sizeDoubleLinkedList(DoubleLinkedList *list) {
    return list->size;
}

// 打印链表的内容
void printDoubleLinkedList(DoubleLinkedList *list) {
    if (list == NULL) {
        return;
    }
    if (list->head == NULL || list->head->next == NULL) {
        return;
    }
    DoubleLinkedListNode *current = list->head->next;
    while (current != list->tail) {
        printf("%d ", current->data);
        current = current->next;
    }
    printf("\n");
}

// 将元素添加到链表末尾
void appendDoubleLinkedList(DoubleLinkedList *list, int value) {
    insertDoubleLinkedList(list, list->size, value);
}

// 弃用旧的追加方法
void appendDoubleLinkedList2(DoubleLinkedList *list, int value) {
    if (list == NULL || list->head == NULL || list->tail == NULL) {
        return;
    }

    // 构造新节点
    DoubleLinkedListNode *node = newDoubleLinkedListNode(value);

    // 插入到末尾
    DoubleLinkedListNode *oldPrev = list->tail->prev;
    oldPrev->next = node;
    node->prev = oldPrev;
    node->next = list->tail;
    list->tail->prev = node;

    // 元素个数增加
    list->size++;
}

// 从链表中移除元素
int removeDoubleLinkedList(DoubleLinkedList *list, int value) {
    int index = -1;
    if (list == NULL || list->head == NULL || list->tail == NULL || list->size <= 0) {
        return index;
    }

    // 查找对应的元素
    DoubleLinkedListNode *current = list->head->next;
    while (current != list->tail) {
        index++;
        if (current->data == value) {
            break;
        }
        current = current->next;
    }

    // 如果找到了,则删除
    if (index >= 0 && index < list->size) {
        DoubleLinkedListNode *oldPrev = current->prev;
        DoubleLinkedListNode *oldNext = current->next;
        oldPrev->next = oldNext;
        oldNext->prev = oldPrev;
        free(current); // 记得释放节点的内存
    }

    // 元素个数减少
    list->size--;

    // 返回
    return index;
}

// 将数据插入到链表指定索引位置
int insertDoubleLinkedList(DoubleLinkedList *list, int index, int value) {
    if (list == NULL || list->head == NULL || list->tail == NULL) {
        return -1;
    }
    // 当一个元素都没有的时候,或者index=size的时候,是支持插入的
    if (index < 0 || index > list->size) {
        return -1;
    }
    // 创建节点
    DoubleLinkedListNode *newNode = newDoubleLinkedListNode(value);

    // 元素个数增加
    list->size++;

    // 插入到头部
    if (index == 0) {
        DoubleLinkedListNode *oldNode = list->head->next;
        list->head->next = newNode;
        newNode->prev = list->head;
        newNode->next = oldNode;
        oldNode->prev = newNode;
        return 0;
    }

    // 插入到尾部
    if (index == list->size) {
        DoubleLinkedListNode *oldNode = list->tail->prev;
        oldNode->next = newNode;
        newNode->prev = oldNode;
        newNode->next = list->tail;
        list->tail->prev = newNode;
        return list->size;
    }

    // 插入到中间
    int i = 0;
    DoubleLinkedListNode *current = list->head->next;
    while (i < index) {
        i++;
        current = current->next;
    }

    // 此时,current就是索引位置的节点,将该节点往后移动
    DoubleLinkedListNode *oldPrev = current->prev;
    oldPrev->next = newNode;
    newNode->prev = oldPrev;
    newNode->next = current;
    current->prev = newNode;

    // 返回
    return index;
}

main.c

#include "double_linked_list.h"

int main(void) {
    // 创建链表
    DoubleLinkedList *list = newDoubleLinkedList();

    // 添加数据
    appendDoubleLinkedList(list, 11);
    appendDoubleLinkedList(list, 22);
    appendDoubleLinkedList(list, 33);
    printDoubleLinkedList(list);

    // 插入到前面
    insertDoubleLinkedList(list,0,333);
    printDoubleLinkedList(list);

    // 插入到后面
    insertDoubleLinkedList(list,list->size,333);
    printDoubleLinkedList(list);

    // 插入到中间
    insertDoubleLinkedList(list,2,333);
    printDoubleLinkedList(list);
    printf("元素个数:%d\n",list->size);

    // 释放链表
    freeDoubleLinkedList(list);

    return 0;
}

输出:

11 22 33
333 11 22 33
333 11 22 33 333
333 11 333 22 33 333
元素个数:6

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/589376.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

免安装SQL管理工具HeidiSQL建库如何选Collation字符校对

免安装SQL管理工具HeidiSQL 文章目录 免安装SQL管理工具HeidiSQL一、安装二、建库因此&#xff0c;通常我们选择&#xff1a; 一、安装 到官方网址&#xff1a;https://www.heidisql.com/ 下载后按不同版本安装或解压&#xff0c;运行目录中的heidisql应用程序。 该工具可以对…

万界星空科技商业开源MES+项目合作+商业开源低代码平台

今天我想和大家分享的是一套商业开源的 MES制造执行管理系统带源码。对于制造业而言&#xff0c;MES 是一个至关重要的系统&#xff0c;它可以帮助企业提高生产效率、优化资源利用、提高产品质量&#xff0c;从而增强市场竞争力。 什么是 MES&#xff1f; MES 是指通过计算机技…

Luminar开始为沃尔沃生产下一代激光雷达传感器

在自动驾驶技术的浪潮中&#xff0c;激光雷达&#xff08;LiDAR&#xff09;传感器以其高精度和强大的环境感知能力&#xff0c;逐渐成为了该领域的技术之星。Luminar&#xff08;路安达&#xff09;公司作为自动驾驶技术的领军企业&#xff0c;近日宣布已开始为沃尔沃汽车生产…

Git使用指北

目录 创建一个Git仓库本地仓库添加文件文件提交到本地仓库缓冲区添加远程仓库地址本地仓库推送到远程仓库创建新的分支拉取代码同步删除缓冲区的文件&#xff0c;远程仓库的文件.gitignore文件 创建一个Git仓库 Git仓库分为远程和本地两种&#xff0c;远程仓库如Githu上创建的…

Themis新篇章:老牌衍生品协议登陆Blast L2,探索全新经济模型

本文将深入分析 Themis 的最新经济模型&#xff0c;探讨其核心概念和机制、优势与创新之处、风险与挑战。 一、引言 随着区块链技术的不断发展&#xff0c;DeFi 衍生品项目逐渐成为市场的焦点。而用户体验的革新&#xff0c;进一步的金融创新&#xff0c;去中心化治理方案的优…

Golang | Leetcode Golang题解之第63题不同路径II

题目&#xff1a; 题解&#xff1a; func uniquePathsWithObstacles(obstacleGrid [][]int) int {n, m : len(obstacleGrid), len(obstacleGrid[0])f : make([]int, m)if obstacleGrid[0][0] 0 {f[0] 1}for i : 0; i < n; i {for j : 0; j < m; j {if obstacleGrid[i]…

Java中使用Redis实现分布式锁的三种方式

1. 导语 随着软件开发领域的不断演进,并发性已经成为一个至关重要的方面,特别是在资源跨多个进程共享的分布式系统中。 在Java中,管理并发性对于确保数据一致性和防止竞态条件至关重要。 Redis作为一个强大的内存数据存储,为在Java应用程序中实现分布式锁提供了一种高效的…

go-mysql-transfer 同步数据到es

同步数据需要注意的事项 前提条件 1 要同步的mysql 表必须包含主键 2 mysql binlog 必须是row 模式 3 不支持程序运行过程中修改表结构 4 要赋予连接mysql 账号的权限 reload, replication super 权限 如果是root 权限则不需要 安装 go-mysql-transfer ​ git clone…

和丰多媒体信息发布系统 QH.aspx 文件上传漏洞复现

0x01 免责声明 请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;作者不为此承担任何责任。工具来自网络&#xff0c;安全性自测&#xff0c;如有侵权请联系删…

《十二》Qt各种对话框之FileDialog文件对话框及QMessageBox 消息对话框

QFileDialog 对话框 选择打开一个文件 若要打开一个文件&#xff0c;可调用静态函数 QFileDialog::getOpenFileName()&#xff0c;“打开一个文件”按钮的响应代码如下&#xff1a; void Dialog::on_btnOpen_clicked() { //选择单个文件QString curPathQDir::currentPath()…

【Docker】如何注册Hub账号并上传镜像到Hub仓库

一、创建Hub账户 浏览器访问&#xff1a;hub.docker.com 点击【Sign up】注册账号 输入【邮箱】【用户名】【密码】 ps&#xff1a;用户名要有字母数字&#xff1b;订阅不用勾选 点击【Sign up】注册即可 点击【Sign in】登录账号 输入【邮箱】【密码】 点击【Continue】登录 二…

大数据之数据仓库技术:ETL工具和Kettle简介

大数据之数据仓库技术&#xff1a;ETL工具和Kettle简介 ETL简介ETL工具和KettleKettle家族 Kettle资源KettlePack 任务调度工具 ETL简介 ETL(Extract-Transform-Load): 在大数据技术领域内&#xff0c;用来描述将数据从 来源端 经过 抽取(extract), 转换(transform), 加载(loa…

cefsharp实现资源替换如网页背景、移除替换标签、html标识、执行javascript脚本学习笔记(含源码说明)

(一)实现测试(仅供学习参考) 1.1 目标系统页面(登录页)和登录后首页面中2处(一个替换一个移除) 1.2 实现后效果(使用cefsharp自定义浏览器实现以上功能) 1.3 登录后页面替换和移除 系统名称和一个功能菜单li (二)通过分析代码实现脚本编写 2.1 分开处理,设置了…

C语言/数据结构——每日一题(反转链表)

一.前言 大家好&#xff01;今天又是每日一题环节。今天我为大家分享了一道单链表题——反转链表。 废话不多说&#xff0c;让我们直接进入正题吧。 二.正文 1.1题目信息 这是一道leetCode上面的一道题&#xff1a;https://leetcode.cn/problems/reverse-linked-list 1.2解…

Linux 第十八章

&#x1f436;博主主页&#xff1a;ᰔᩚ. 一怀明月ꦿ ❤️‍&#x1f525;专栏系列&#xff1a;线性代数&#xff0c;C初学者入门训练&#xff0c;题解C&#xff0c;C的使用文章&#xff0c;「初学」C&#xff0c;linux &#x1f525;座右铭&#xff1a;“不要等到什么都没有了…

一周零碎时间练习微服务(nacos,rq,springcloud,es等)内容

目录 1 总览1.1 技术架构1.2 其他1.2.1 数据库1.2.2 后端部分1.2.2.1 复习feign1.2.2.2 复习下网关网关的核心功能特性&#xff1a;网关路由的流程断言工厂过滤器工厂全局过滤器 过滤器执行顺序解决跨域问题 1.2.2.3 es部分复习 1.2.3 前端部分 2 day1 配置网关2.1 任务2.2 网关…

UI-Diffuser——使用生成性人工智能的UI原型设计

概述。 移动UI是影响参与度的一个重要因素&#xff0c;例如用户对应用的熟悉程度和使用的便利性。如果你有一个类似的应用程序&#xff0c;你可能会选择一个具有现代、好看的设计的应用程序&#xff0c;而不是一个旧的设计。然而&#xff0c;要从头开始研究什么样的UI最适合应…

JavaEE >> Spring MVC(1)

MVC MVC&#xff1a;Model View Controller 的缩写&#xff0c;是一种软件架构模式&#xff0c;将软件系统分为模型、视图和控制器三个部分。 Mode&#xff08;模型&#xff09;&#xff1a;是应⽤程序中⽤于处理应⽤程序数据逻辑的部分。通常模型对象负责在数据库中存取数据…

【通信中间件】Fdbus HelloWorld实例

Fdbus实例教程 Fdbus简介 Fdbus 全称 Fast Distributed Bus&#xff08;高速分布式总线&#xff09;&#xff0c;提供IPCRPC功能。适用于多种OS&#xff1a; LinuxQNXAnroidOSWindow Fdbus本质是Socket&#xff0c;IPC基于Unix domain socket&#xff0c;RPC基于TCP。使用G…

CAMEL:大型语言模型社会的“心智”探索沟通代理

英文名称: CAMEL: Communicative Agents for “Mind” Exploration of Large Language Model Society 中文名称: CAMEL&#xff1a;大型语言模型社会的“心智”探索沟通代理 链接: https://arxiv.org/pdf/2303.17760.pdf 代码: https://github.com/camel-ai/camel 4.4K Star 作…
最新文章