C语言超详细i讲解双向链表

C语言超详细讲解双向链表

什么是双向链表

双向链表是一个动态数据结构,它由一系列的节点构成,每个节点分为三部分:数据域、指向前驱节点的指针和指向后继节点的指针。双向链表支持在任意位置插入或删除节点,与数组相比,它具有更好的灵活性和效率。

如何实现双向链表

定义节点

typedef struct DNode {
    int data;
    struct DNode* prev;
    struct DNode* next;
}DNode, *DLinkList;

创建节点

//创建节点
DNode* create_node(int data) {
    DNode* node = (DNode*)malloc(sizeof(DNode));
    node->data = data;
    node->prev = NULL;
    node->next = NULL;
    return node;
}

插入节点

头部插入节点

//头部插入节点
void insert_head(DLinkList* head, DNode* node) {
    if (node == NULL) {
        return;
    }
    node->next = *head;
    node->prev = NULL;
    if (*head != NULL) {
        (*head)->prev = node;
    }
    *head = node;
}

尾部插入节点

//尾部插入节点
void insert_tail(DLinkList* head, DNode* node) {
    if (node == NULL) {
        return;
    }
    if (*head == NULL) {
        *head = node;
        node->prev = NULL;
        node->next = NULL;
    }
    else {
        DNode* p = *head;
        while (p->next != NULL) {
            p = p->next;
        }
        node->prev = p;
        node->next = NULL;
        p->next = node;
    }
}

按位置插入节点

//按位置插入节点
void insert_pos(DLinkList* head, DNode* node, int pos) {
    if (node == NULL) {
        return;
    }
    if (*head == NULL || pos <= 1) {
        node->prev = NULL;
        node->next = *head;
        if (*head != NULL) {
            (*head)->prev = node;
        }
        *head = node;
    }
    else {
        DNode* p = *head;
        int i = 1;
        while (p->next != NULL && i < pos-1) {
            p = p->next;
            i++;
        }
        node->prev = p;
        node->next = p->next;
        if (p->next != NULL) {
            p->next->prev = node;
        }
        p->next = node;
    }
}

删除节点

删除头部节点

//删除头部节点
void delete_head(DLinkList* head) {
    if (*head != NULL) {
        DNode* p = *head;
        *head = (*head)->next;
        if (*head != NULL) {
            (*head)->prev = NULL;
        }
        free(p);
    }
}

删除尾部节点

//删除尾部节点
void delete_tail(DLinkList* head) {
    if (*head != NULL) {
        DNode* p = *head;
        while (p->next != NULL) {
            p = p->next;
        }
        if (p->prev != NULL) {
            p->prev->next = NULL;
        }
        else {
            //删除头部节点
            *head = NULL;
        }
        free(p);
    }
}

按位置删除节点

//按位置删除节点
void delete_pos(DLinkList* head, int pos) {
    if (*head != NULL && pos >= 1) {
        if (pos == 1) {
            //删除头部节点
            delete_head(head);
        }
        else {
            DNode* p = *head;
            int i = 1;
            while (p->next != NULL && i < pos) {
                p = p->next;
                i++;
            }
            if (i == pos && p != NULL) {
                if (p->prev != NULL) {
                    p->prev->next = p->next;
                }
                if (p->next != NULL) {
                    p->next->prev = p->prev;
                }
                free(p);
            }
        }
    }
}

示例说明

插入节点示例

//创建双向链表
DLinkList head = NULL;
int n, i, data;
printf("请输入节点个数:");
scanf("%d", &n);
for (i = 1; i <= n; i++) {
    printf("请输入第%d个节点的数据:", i);
    scanf("%d", &data);

    //创建节点
    DNode* node = create_node(data);

    //头部插入节点
    //insert_head(&head, node);

    //尾部插入节点
    insert_tail(&head, node);

    //按位置插入节点
    //insert_pos(&head, node, i);
}

//遍历双向链表
DNode* p = head;
printf("双向链表元素:");
while (p != NULL) {
    printf("%d ", p->data);
    p = p->next;
}

删除节点示例

//创建双向链表
DLinkList head = NULL;
int n, i, data;
printf("请输入节点个数:");
scanf("%d", &n);
for (i = 1; i <= n; i++) {
    printf("请输入第%d个节点的数据:", i);
    scanf("%d", &data);

    //创建节点
    DNode* node = create_node(data);

    //头部插入节点
    insert_head(&head, node);

    //尾部插入节点
    //insert_tail(&head, node);

    //按位置插入节点
    //insert_pos(&head, node, i);
}

//删除双向链表中第3个节点
delete_pos(&head, 3);

//遍历双向链表
DNode* p = head;
printf("双向链表元素:");
while (p != NULL) {
    printf("%d ", p->data);
    p = p->next;
}

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言超详细i讲解双向链表 - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • win10下定时运行与开机自启动jar包的方法记录

    我来给你详细讲解win10下定时运行与开机自启动jar包的方法。我们可以分为两个部分来讲解,下面将分别进行详细介绍。 一、定时运行jar包的方法记录 1.安装JRE环境 在运行Java程序之前,需要安装Java Runtime Environment(JRE)环境。可以在官网下载安装。 2.运行jar包 运行jar包有多种方法,我们这里介绍一种简单的方法:使…

    C 2023年5月22日
    00
  • jQuery自带的一些常用方法总结

    jQuery是什么?jQuery是一款流行的JavaScript库,具有优秀的跨浏览器兼容性和出色的HTML文档操作、事件处理、动画效果、AJAX以及插件扩展等功能。 jQuery自带的一些常用方法总结: HTML文档操作 .html(): 获取或设置匹配元素集合中的HTML内容。 用法示例: “` // 获取元素的HTML内容 var htmlConte…

    C 2023年5月23日
    00
  • C 程序 八进制转换为十进制

    让我详细讲解一下如何使用C语言编写程序来将八进制转换为十进制。 1. 程序说明 首先,需要说明一下本程序的功能和使用方法。本程序是用来将八进制数转换为十进制数的,它通过输入一个八进制数,输出对应的十进制数。程序包含一个函数,该函数可以接受输入的八进制数,在内部进行转换,并将得到的十进制数返回。 2. 算法原理 本程序的转换算法非常简单,只需要将每一位八进制数…

    C 2023年5月9日
    00
  • C语言求Fibonacci斐波那契数列通项问题的解法总结

    C语言求Fibonacci斐波那契数列通项问题的解法总结 问题描述 Fibonacci数列是一个非常经典的数学问题,定义如下: F(0) = 0 F(1) = 1 F(n) = F(n-1) + F(n-2) (n>=2) 要求编程实现Fibonacci数列的通项公式求解。 思路分析 Fibonacci数列的通项公式可以用公式表示,通项公式如下: $$…

    C 2023年5月22日
    00
  • VC6.0如何创建以及调用动态链接库实例详解

    本篇攻略将详细讲解如何使用VC6.0创建和调用动态链接库实例。动态链接库常用于将一些公共的函数库分离出来,供不同的程序共享,节省程序的内存空间和提高代码的重复利用程度。 1. 创建动态链接库 在VC6.0中,创建动态链接库需要以下步骤: 1.1 新建Win32控制台应用程序 打开VC6.0,选择菜单中的 “文件” -> “新建” -> “项目”,…

    C 2023年5月23日
    00
  • C语言实现家庭理财系统

    C语言实现家庭理财系统 简介 家庭理财系统是一款针对家庭财务管理的软件,可以记录家庭的收入和支出情况,帮助用户实现对家庭财务的有效管理和实时监控。本文介绍如何使用C语言实现一个家庭理财系统。 系统设计 家庭理财系统可以分为三个模块:界面模块、数据管理模块和报表模块。 界面模块 界面模块是用户与系统交互的界面。在本系统中,可以通过命令行界面输入和输出数据。 界…

    C 2023年5月23日
    00
  • C++内核对象封装单实例启动程序的类

    针对这个话题,我来给你详细讲解一下。 什么是C++内核对象封装单实例启动程序的类 C++内核对象封装单实例启动程序的类,是一种用C++编写的程序类,可以确保只有一个实例被启动运行,防止多次启动同一程序时造成的冲突和不必要的资源浪费。该类通常会使用操作系统的内核对象来进行进程管理和控制,保证只有一个实例在运行。 如何实现C++内核对象封装单实例启动程序的类 下…

    C 2023年5月22日
    00
  • Java编程基础测试题分享

    Java编程基础测试题分享攻略 背景说明 Java编程入门的学习是需要实践的。而测试题是测试自己知识掌握情况的重要方式之一。本文将介绍如何准备Java编程基础测试题,以及如何完整的解答测试题,帮助初学者更好地进行自我学习和检验。 准备测试题 找到适当的测试题,可以在网上搜索一些Java编程基础测试题,或者向周围有经验者拿一些推荐的Java编程基础测试题 将测…

    C 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部