基础数据结构之双向链表

news2024/11/17 13:25:26

目录

 基础定义

节点的定义

节点的初始化

创建双链表

1.前插法

2.尾插法

双向链表的遍历输出

指定位置插入

双向链表的按位取值

任意位置删除

双向链表销毁

主程序入口​​​​​​​

 基础定义

所谓的双向链表就是单向链表多了一个前驱指针。双向链表是由一个个结点组成每个结点之间通过链接关系串联起来每个结点都有前驱结点和后继结点第一个结点的前驱结点为空结点最后一个结点的后继结点为空结点。

由链接关系A <- >B组织起来的两个结点B被称为A的后继结点A被称为B的前驱结点因为是双向的所以被称为双向链表由于链表是由一个个结点组成。

节点的定义

// c++ 代码示例

typedef struct DoubleLinkList
{
    int data ;
    DoubleLinkList* prev ;
    DoubleLinkList* next ;
}DoubleLinkList, DoubleLinkNode ;
# python 代码示例

class DoubleLinkList :
    def __init__(self, val) :
        self.val = val
        self.next = None
        self.pre = None
        #  None <- 节点 -> None

节点的初始化

// c++ 代码示例

bool DoubleLinkListInit(DoubleLinkList* &L)
{
    L = new DoubleLinkNode ;
    if (!L)
    {
        return false ;
    }
    L -> prev = NULL ;
    L -> next = NULL ;
    L -> data = -1 ;
    return true ;
}
# python 代码示例
class DoubleLinkNode :
    def __init__(self, data = None) :
        self.data = data
        self.next = None
        self.prev = None
def DoubleLinkListInit() :
    try :
        L = DoubleLinkNode()
        L.data = -1
        return L
    except Exception as e :
        print(f"Error Initializing List: {e}")
        return None
# 使用示例
L = DoubleLinkListInit()
if L:
    print("双向链表初始化成功")
else:
    print("双向链表初始化失败")


        

创建双链表

1.前插法
bool DoubleLinkInsertFront(DoubleLinkList*& L, DoubleLinkNode* node)
{
    if (!L || !node)
    {
        return false ;
    }
    if (L -> next == NULL)
    {
        node -> next = NULL ;
        node -> prev = L ;
        L -> next = node ;
    }
    else
    {
        L -> next -> prev = node ;
        node -> next = L -> next ;
        node -> prev = L ;
        L -> next = node ;
    }
    return true ;

}
# python 代码示例

def double_link_insert_front(L, node):  
    if L is None or node is None:  
        return False  
    
    if L.next is None:  
        node.next = None  
        node.prev = L  
        L.next = node  
    else:  
        L.next.prev = node  
        node.next = L.next  
        node.prev = L  
        L.next = node  
    
    return True  
2.尾插法
# python 代码示例

def double_link_list_insert_back(L, node):  
    if L is None or node is None:  
        return False  
    
    last = L  
    while last.next:  
        last = last.next  
    
    node.next = None  
    node.prev = last  
    last.next = node  
    
    return True  
// c++ 代码示例
bool DoubleLinkListInsertBack(DoubleLinkList*& L, DoubleLinkNode* node)
{
    DoubleLinkNode* last = NULL ;
    if (!L || !node)
    {
        return false ;
    }
    last = L ;  
    while (last -> next)
    {
        last = last -> next ;
    }
    node -> next = NULL ;
    node -> prev = last ;
    last -> next = node ;
    return true ;
}

双向链表的遍历输出

// c++ 代码示例

void DoubleLinkListPrint(DoubleLinkList* &L)
{
    DoubleLinkNode* p = L ;
    if (!L)
    {
        cout << "链表为空" << endl ;
        return ;
    }
    cout << p -> data << " " ;
    while (p -> next)
    {
        cout << p -> next -> data << " " ;
        p = p -> next ;
    }
    
    cout << endl << "逆向打印" << endl ;
    while (p)
    {
        cout << p -> data << " " ;
        p = p -> prev ;
    }
    cout << endl ;
    return ;
}
# python 代码示例

ef double_link_list_print(L):  
    if L is None:  
        print("链表为空")  
        return  
    
    p = L  
    print(p.data, end=" ")  
    
    while p.next:  
        p = p.next  
        print(p.data, end=" ")  
    
    print("\n逆向打印")  
    
    while p:  
        print(p.data, end=" ")  
        p = p.prev  
    
    print()  

指定位置插入

// c++代码示例

bool DoubleLinkListInsert(DoubleLinkList* L, int i, int e)
{
    if (!L || !L -> next)
    {
        return false ;
    }
    if (i < 1)
    {
        return false ;
    }
    int j = 0 ;
    DoubleLinkList* p , * s ;
    p = L ;
    
    while (p && j < i)
    {
        p = p -> next ;
        j++ ;
    }
    if (!p || j != i)
    {
        cout << "结点不存在" << i << endl ;
        return false ;
    }

    s = new DoubleLinkNode ;
    s -> data = e ;   

    s -> next = p ;
    s -> prev = p -> prev ;
    p -> prev -> next = s ;
    p -> prev = s ;

    return true ;
}
# python 代码示例

def double_link_list_insert(L, i, e):  
    if L is None or L.next is None:  
        return False  
    
    if i < 1:  
        return False  
    
    j = 0  
    p = L  
    
    while p and j < i:  
        p = p.next  
        j += 1  
    
    if p is None or j != i:  
        print(f"结点不存在 {i}")  
        return False  

    s = DoubleLinkNode(data=e)  

    s.next = p  
    s.prev = p.prev  
    p.prev.next = s  
    p.prev = s  

    return True  

双向链表的按位取值

// c++ 代码示例

bool DoubleLinkListGetElem(DoubleLinkList* &L, int i, int& e)
{
    int index ;
    DoubleLinkList* p ;
    
    if (!L || !L -> next)
    {
        return false ;
    }
    p = L -> next ;
    index = 1 ;
    
    while (p || index < i)
    {
        p = p -> next ;    
        index++ ;
    }
    if (!p || index > i)
    {
        return false ;
    }
    e = p -> data ;
    return true ;
}
# python 代码示例

def double_link_list_get_elem(L, i):  
    if L is None or L.head.next is None:  
        return False, None  
    
    p = L.head.next  
    index = 1  
    
    while p and index < i:  
        p = p.next  
        index += 1  
    
    if p is None or index > i:  
        return False, None  
    
    return True, p.data 

任意位置删除

// c++ 代码示例

bool DoubleLinkListDelete(DoubleLinkList*& L, int i)
{
    DoubleLinkList* p ;
    int index = 0 ;
    if (!L || !L -> next)
    {
        cout << "双向链表为空!" << endl ;
        return false ;
    }
    if (i < 1 ) 
    {
        cout << "不能删除头结点!" << endl ;
        return false ;
    }
    p = L ;
    while (p && index < i)
    {
        p = p -> next ;
        index++ ;
    }
    if (!p)
    {
        return false ;
    }
    p -> prev -> next = p -> next ;
    if (p -> next != nullptr)
    {
        p -> next -> prev = p -> prev ;
    }
    delete p ;
    return true ;
}
# python 代码示例


def double_link_list_delete(L, i):  
    if L is None or L.head.next is None:  
        print("双向链表为空!")  
        return False  
    
    if i < 1:  
        print("不能删除头结点!")  
        return False  
    
    p = L.head.next  
    index = 1  
    
    while p and index < i:  
        p = p.next  
        index += 1  
    
    if p is None:  
        return False  
    
    # 更新前后节点的链接  
    p.prev.next = p.next  
    if p.next is not None:  
        p.next.prev = p.prev  
    
    del p  # 删除节点  
    return True  

双向链表销毁

// c++ 代码示例

void DoubleLinkListDestory(DoubleLinkList* &L)
{
    DoubleLinkList* p = L ;
    cout << "销毁链表" << endl ;
    while (p)
    {
        L = L -> next ;
        delete p ;
        p = L ;
    }
}
# python 代码示例

def double_link_list_destroy(L):  
    print("销毁链表")  
    p = L.head  # 从头节点开始  
    while p:  
        next_node = p.next  # 保存下一个节点  
        del p  # 删除当前节点  
        p = next_node  # 移动到下一个节点  
    L.head = None  # 清空链表的头节点引用  

主程序入口

// c++ 代码示例
int main()
{
    DoubleLinkList* L ;
    DoubleLinkList* s ;
    
    if (DoubleLinkListInit(L))
    {
        cout << "初始化链表成功!" << endl ;
    }
    else
    {
        cout << "初始化链表失败!" << endl ;
    }
    int n ;
    cout << "前插法" << endl ;
    cout << "输入元素个数" ;
    cin >> n ;
    cout << endl << "依次输入" << n << "个元素:" ;
    while ( n > 0 )
    {
        s = new DobleLinkNode ;
        cin >> s -> data ;
        DoubleLinkListInsertFront(L, s) ;
        n-- ;
    }
    
    DoubleLinkListPrint(L) ;
    for (int j = 0 ; j < 3 ; j++)
    {
        int i , x ;
        cout << "请输入要插入的位置和元素(用空格隔开)" ;
        cin >> i >> x ;
        if (DoubleLinkListInsert(L, i, x))
        {
            cout << "插入成功!" << endl ;
        }
        else
        {
            cout << "插入失败!" << endl ;
        }
        DoubleLinkListPrint(L) ;
    }
    if (DoubleLinkListDelete(L, 2))
    {
        cout << "删除链表第2个元素成功!" << endl ;
    }
    else
    {
        cout << "删除链表第2个元素失败!" << endl ;
    }

    DoubleLinkListPrint(L);

	DoubleLinklistDestroy(L);


	return 0;
}
# python 代码示例

def main():  
    L = DoubleLinkList()  
    print("初始化链表成功!")  

    n = int(input("前插法\n输入元素个数: "))  
    print(f"依次输入 {n} 个元素:")  
    while n > 0:  
        data = input()  
        node = DoubleLinkListNode(data)  
        L.insert_front(node)  
        n -= 1  

    L.print_list()  
    
    for _ in range(3):  
        i, x = map(int, input("请输入要插入的位置和元素(用空格隔开): ").split())  
        new_node = DoubleLinkListNode(x)  
        if L.insert_front(new_node) and L.delete(i):  
            print("插入成功!")  
        else:  
            print("插入失败!")  
        L.print_list()  

    if L.delete(2):  
        print("删除链表第2个元素成功!")  
    else:  
        print("删除链表第2个元素失败!")  

    L.print_list()  
    L.destroy()  


if __name__ == "__main__":  
    main() 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【LLM】大模型基础--大规模预训练语言模型的开源教程笔记

1.引言 本文以DataWhale大模型开源教程为学习路线&#xff0c;进行一整个大模型的入门操作 什么是语言模型 语言模型是一种对词元序列&#xff08;token&#xff09;的概率分布&#xff0c;可以用于评估文本序列的合理性并生成新的文本。 从生成文本的方式来看&#xff0c;…

【C++ Primer Plus习题】10.4

问题: 解答: main.cpp #include <iostream> #include "sales.h" using namespace std; using namespace SALES;int main() {Sales s1;double de[QUARTERS] { 12.1,32.1,42.1,51.1 };Sales s2(de, QUARTERS);s1.showSales();s2.showSales();return 0; }sales.…

IP/TCP/UDP协议的关键知识点

导语&#xff1a;网络协议是理解网络情况的基础&#xff0c;当遇到网络问题时&#xff0c;首先可以从网络协议入手&#xff0c;熟悉的网络协议可以有效帮助小伙伴们排查或者说定位大概的问题方面。本文整理了目前最常用的网络通信协议&#xff0c;相信对小伙伴们肯定都有帮助。…

C#使用MQTT(一):MQTT服务端

MQTT&#xff08;Message Queuing Telemetry Transport&#xff09; 即时通讯协议&#xff0c; 开发商 IBM MQTT(消息队列遥测传输)是ISO 标准(ISO/IEC PRF 20922)下基于发布/订阅范式的消息协议。它工作在 TCP/IP协议族上&#xff0c;是为硬件性能低下的远程设备以及网络状…

将RK3588平台的TMC等USB function驱动挪出内核源码树

背景 前一段时间定位一个上位机通过USB-TMC连接下位机&#xff08;基于RK3588平台&#xff09;时界面发生卡顿的问题&#xff0c;发现USB-TMC驱动代码是放在内核源码树里跟内核一起编译的&#xff0c;觉着这样既不便于更换TMC 驱动版本&#xff08;每次修改代码都要重编内核&a…

2024年【广西安全员C证】考试题及广西安全员C证考试技巧

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 广西安全员C证考试题是安全生产模拟考试一点通生成的&#xff0c;广西安全员C证证模拟考试题库是根据广西安全员C证最新版教材汇编出广西安全员C证仿真模拟考试。2024年【广西安全员C证】考试题及广西安全员C证考试技…

AI电商产品一键换高清背景,就是这么简单(comfyui)

comfyui电商产品换背景工作流 工作流作者&#xff1a;Aki Hung c 工作流我放在了文末&#xff0c;需要的朋友自取&#xff01; 这里给大家准备好了一份详细的ComfyUI资料和安装包&#xff0c;扫描下方二维码即可获取&#xff01; 大家好&#xff0c;我是你们的老朋友&#xf…

10.4 网际层协议

网际层协议 真题

YashanDB产品调优实战:分享日常调优技巧及提升系统性能的实战经验

本文旨在提供一系列关于YashanDB产品的调优技巧和实战经验&#xff0c;帮助读者更好地理解和应用这些技术来优化数据库性能。内容将涵盖索引优化、查询优化、内存管理、参数配置&#xff0c;以及性能监控等多个方面&#xff0c;通过实际案例和详细的分析&#xff0c;展示如何有…

程序员学python的七大就业方向!

Python作为一种多功能的编程语言&#xff0c;其就业方向广泛且前景乐观。以下是Python的七大就业方向&#xff1a; Web开发&#xff1a; Python在Web开发领域具有重要地位&#xff0c;拥有Flask、Django等优秀的Web开发框架&#xff0c;可以快速搭建网站和Web应用。这些框架不仅…

【Redis】缓存击穿、缓存穿透、缓存雪崩原理以及多种解决方案

一、前言 在 Spring Cloud 微服务集群项目中&#xff0c;客户端的请求首先会经过 Nginx&#xff0c;Nginx 会将请求反向代理到 Gateway 网关层&#xff0c;接着才会将请求发送到具体的服务 service。 在 service 中如果要查询数据&#xff0c;则会到缓存中查询&#xff0c;如…

COT思维链,TOT思维树,GOT思维图,这些都是什么?

1. 导入 hallucinations 1. 什么是幻觉&#xff1f; 大模型出现幻觉&#xff0c;简而言之就是“胡说八道”。 用《A Survey on Hallucination in Large Language Models》文中的话来讲&#xff0c;是指模型生成的内容与现实世界事实或用户输入不一致的现象。 研究人员将大模型…

基于精益六西格玛管理方法进行生产线综合改善

生产线精益六西格玛改善是一个系统工程&#xff0c;只有对其进行系统的策划与组织&#xff0c;才能收到良好的改善效果。一般来说&#xff0c;需要成立一个专门的精益六西格玛推进组织&#xff0c;由其完成一系列的组织、准备工作。具体如下&#xff1a; &#xff08;1&#xf…

AutosarMCAL开发——基于EB FlsLoader驱动

目录 1.FlsLoader原理2.EB配置以及接口应用3.总结 1.FlsLoader原理 FlsLoader模块提供对Dflash bank0以及整个Pflash的操作。Dflash数据存储器Pflash程序储存器&#xff0c;因此在实际运用中 2.EB配置以及接口应用 EB配置步骤 1.取消安全检查&#xff0c;其他所有配置保持默…

《物流工程与管理》是什么级别的期刊?是正规期刊吗?能评职称吗?

​问题解答 问&#xff1a;《物流工程与管理》是不是核心期刊&#xff1f; 答&#xff1a;不是&#xff0c;是知网收录的第一批认定学术期刊。 问&#xff1a;《物流工程与管理》级别&#xff1f; 答&#xff1a;国家级。主管单位&#xff1a; 全国商品养护科技情报中心站 …

mongodb在Java中条件分组聚合查询并且分页(时间戳,按日期分组,年月日...)

废话不多说&#xff0c;先看效果图&#xff1a; SQL查询结果示例&#xff1a; 多种查询结果示例&#xff1a; 原SQL&#xff1a; db.getCollection("hbdd_order").aggregate([{// 把时间戳格式化$addFields: {orderDate: {"$dateToString": {"for…

分类预测|基于蜣螂优化极限梯度提升决策树的数据分类预测Matlab程序DBO-Xgboost 多特征输入单输出 含基础模型

分类预测|基于蜣螂优化极限梯度提升决策树的数据分类预测Matlab程序DBO-Xgboost 多特征输入单输出 含基础模型 文章目录 一、基本原理1. 数据准备2. XGBoost模型建立3. DBO优化XGBoost参数4. 模型训练5. 模型评估6. 结果分析与应用原理总结 二、实验结果三、核心代码四、代码获…

龙兴物联5G物联网主机:开启电力智能化新篇章

在当今时代&#xff0c;电力行业的智能化已成为不可阻挡的趋势。随着社会对电力需求的持续增长以及对供电质量和可靠性要求的不断提高&#xff0c;传统的电力系统管理模式逐渐难以满足需求。 智能化技术的融入为电力系统带来了革命性的变革。通过先进的传感器、通信网络和数据分…

ELK系列之一---探索ELK奇妙世界:初识日志界大名鼎鼎的ES集群!

目录 一、为什么要使用ELK 二、ELK简介 三、Elaticsearch入门 3.1、什么是elaticsearch 3.2、elaticsearch的底层优点 3.2.1、全文检索 3.2.2、倒排索引 3.3、elaticsearch集群原理 一、为什么要使用ELK 一般我们需要进行日志分析场景&#xff1a;直接在日志文件中 gre…

Linux -文件I/O操作

文章目录 C语言文件I/O相关函数操作fopen/fcolsefwritefseekfprintf/fscanffgets/fputs 系统调用相关接口open/closewrite/read C语言文件I/O相关函数操作 fopen/fcolse fopen 函数用于打开一个文件&#xff0c;并根据指定的模式&#xff08;如只读、只写、读写等&#xff09…