IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> ch2_3 双链表的设计_python, 节点的增加,删除; -> 正文阅读

[数据结构与算法]ch2_3 双链表的设计_python, 节点的增加,删除;

1.双链表的定义

1.1 节点的定义

双链表中节点: 一个节点中 包括数值, 前指针, 后指针;

class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None
        self.prev = None

1.2 链表的初始化

哨兵节点 产生两个 伪节点:
sentinel nodes as pseudo-head and pseudo-tail
包含了 伪头节点, 和 伪 尾节点;

class MyLinkedList:
    def __init__(self):
        self.size = 0
        # sentinel nodes as pseudo-head and pseudo-tail
        self.head, self.tail = ListNode(0), ListNode(0) 
        self.head.next = self.tail
        self.tail.prev = self.head

在这里插入图片描述

2. 实现重点:

  1. 寻找前驱节点和 后继节点时, 先判断 从短的 一端开始:
  2. 如果 目标节点 靠近 头节点, 从 伪头节点开始
  3. 如果目标节点靠近 尾节点, 从 伪 尾节点开始

2.1 链表 中 节点的 插入;

addAtIndex,addAtHead 和 addAtTail:

找到要插入节点的前驱节点和后继节点。如果要在头部插入节点,则它的前驱结点是伪头。如果要在尾部插入节点,则它的后继节点是伪尾。
通过改变前驱结点和后继节点的链接关系添加元素。

to_add.prev = pred
to_add.next = succ
pred.next = to_add
succ.prev = to_add

在这里插入图片描述

2.2 链表 中 节点的 删除;

deleteAtIndex:
和插入同样的道理。

找到要删除节点的前驱结点和后继节点。
通过改变前驱结点和后继节点的链接关系删除元素

pred.next = succ
succ.prev = pred

在这里插入图片描述

2.2 链表 中 节点的 获取;

get:

通过比较 index 和 size - index 的大小判断从头开始较快还是从尾巴开始较快。
从较快的方向开始。

# choose the fastest way: to move from the head
# or to move from the tail
if index + 1 < self.size - index:
    curr = self.head
    for _ in range(index + 1):
        curr = curr.next
else:
    curr = self.tail
    for _ in range(self.size - index):
        curr = curr.prev

在这里插入图片描述

3 双链表的完整代码;

class LinkNode:
    def __init__(self, x):
        self.val = x
        self.prev = None
        self.next = None

class BiLinkList:
    def __init__(self):
        self._head = LinkNode(None)
        self._tail = LinkNode(None)  # sentinel nodes as pseudo-head node and pseudo-tail
        self._count = 0
        self._head.next = self._tail
        self._tail.prev = self._head


    def get(self, index: int) -> int:
        if index < 0 or index >= self._count:
            return
         # 判断从 短的那一端测开始,
         # 此处 Index + 1: 代表 考虑当只有一个元素时的情况,
        if index +1 < self._count - index:  
            cur = self._head     #   目标节点靠近头节点, 则从伪头节点开始;
            for _ in range(index + 1):
                cur = cur.next
        else:
            #  目标节点靠近尾节点 , 则从伪 尾节点开始, 往前推进的次数;
            cur = self._tail
            for _ in  range(self._count - index): 
                cur = cur.prev

        return  cur.val

     # pred: predecessor: 前驱节点   successor: 后继节点;
    def addAtIndex(self, index:int, val: int) -> None:
        if index >= self._count:
            return
        if index < 0:
          index = 0
          
   		# 判断从 短的那一端测开始,
        if index  < self._count - index:
            pred = self._head             # pred  从 伪头节点 开始 往后走;
            for _ in range(index):
                pred = pred.next    # 此时 循环结束后, pred 代表 插入节点的 前驱节点;
            succ =  pred.next             # succ 代表插入节点的 后继节点;

        else:         # 否则,当index 靠近尾节点时,  从伪尾节点开始 往前走;
            succ = self._tail
            for _ in range(self._count - index):   # 此时 _count - index : 代表往前走的次数;
                succ = succ.prev
            pred = succ.prev

        add_node = LinkNode(val)  # 初始化节点,
        self._count +=  1       #   链表节点 个数 加 一;

        add_node.next = succ
        add_node.prev = pred

        pred.next = add_node
        succ.prev = add_node

    def addAtHead(self, val: int) -> None:
        add_node = LinkNode(val)
        self._count += 1

        pred = self._head
        succ = self._head.next

        add_node.prev = pred
        add_node.next = succ
        pred.next = add_node
        succ.prev = add_node

    def addAtTail(self, val: int) -> None:

        add_node = LinkNode(val)
        self._count += 1

        succ = self._tail
        pred = self._tail.prev

        add_node.prev = pred
        add_node.next = succ
        pred.next = add_node
        succ.prev = add_node

    def delete(self, index) -> None:
        if index < 0 or index >= self._count:
            return

        if index   < self._count - index:
            pred = self._head
            for _ in range(index):
                pred = pred.next
            succ  = pred.next.next
        else:
            succ = self._tail
            # 注意这里是 删除Index 节点, 能够取得到index 处, 故需要 减一;
            for _ in range(self._count - index - 1 ):   
                succ = succ.prev
            pred = succ.prev.prev


        self._count -= 1
        pred.next = succ
        succ.prev = pred

    def removeElements(self, target: int) -> None:


    def traversal(self,) -> None:
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-02-26 11:55:08  更:2022-02-26 11:56:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 16:34:36-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码