python实现单链表、双链表、反转链表(二)

一、链表概述

链表是有元素组成的数据结构,每个元素都是单独对象,包含数据和指针信息

链表中的每个元素称为节点,如下所示,第一个节点称为Head(头节点),为链表的入口点,如果链表为空,则Head指向None,链表的最后一个节点指向None
在这里插入图片描述

如上图所示,链表是动态数据结构,无法直接访问数据,搜索任何项都需要从Head开始,必须遍历每个引用才能获取节点信息,链表占用更多内存

二、单链表

单链表是只包含数据和指向下一个引用的数据结构,最后一个节点对象没有引用

定义一个Node类,包括数据data和引用下一个引用reference, 默认下一个reference为None

每创建一个Node类, 将上一个Node类的reference指向当前创建,遍历链表需要从第一个节点开始,如presentNode = objNode1,依次获取当前节点的下一个引用,即为遍历,分配变量presentNode之后, 最后一个节点包含指针值,将推出while循环,因为指针值为None,代码实现如下所示

class Node:
    def __init__(self, data=None):
        """
        创建Node类,包括data(值)和reference(下一个指针)
        :param data:
        """
        self.data = data
        self.reference = None


if __name__ == '__main__':
    objNode1 = Node(1)
    objNode2 = Node(2)
    objNode3 = Node(3)
    objNode4 = Node(4)
    objNode1.reference = objNode2
    objNode2.reference = objNode3
    objNode3.reference = objNode4
    presentNode = objNode1
    while presentNode:
        print("当前Node值为:", presentNode.data)
        presentNode = presentNode.reference

将遍历信息封装,同时创建Linked_list类,目的是 对Node信息进行管理和操作,定义Linked_list类, 保存头节点位置,同时定义指针信息,如下图所示:
在这里插入图片描述

代码如下所示

class Node:
    def __init__(self, data=None):
        """
        创建Node类,包括data(值)和reference(下一个指针)
        :param data:
        """
        self.data = data
        self.reference = None


class Linked_list:
    def __init__(self):
        self.head = None

    def recursive(self):
        """
        定义遍历节点类
        :return:
        """
        presentNode = self.head
        while presentNode:
            print("当前Node值为:", presentNode.data)
            presentNode = presentNode.reference


if __name__ == '__main__':
    objNode1 = Node(1)
    objNode2 = Node(2)
    objNode3 = Node(3)
    objNode4 = Node(4)
    linkObj = Linked_list()
    linkObj.head = objNode1
    linkObj.head.reference = objNode2
    objNode2.reference = objNode3
    objNode3.reference = objNode4
    linkObj.recursive()

如果在链表添加头节点,只需令linkObj.head = new_node和new_node.reference = objNode1

如方法 insert_at_head(data),

  • 首先需要创建一个新节点,此时并未指向任何信息

  • 将当前新节点引用指向当前链表的头节点

  • 然后将头节点指针指向当前节点,即可完成新节点添加

def insert_at_head(self, data):
    """
    链表头部添加新数据
    :param data:
    :return:
    """
    new_data = Node(data)
    # 此处奇妙在,新节点的引用,指向当前链表的头节点,然后在将头节点指针前移,指向新节点即可
    new_data.reference = self.head
    self.head = new_data

如果在链表添加尾节点,需要遍历整个链表,找出当前尾节点,然后将当前尾节点引用,指向新的节点

def insert_at_end(self, data):
    """
    链表尾部添加新数据
    :param data:
    :return:
    """
    new_data = Node(data)
    presentNode = self.head
    while presentNode:
        presentNode = presentNode.reference
    presentNode.reference = new_data

在两个节点之间插入新节点,需要先获取当前节点的引用节点,并把引用节点赋值给待添加节点,同时将当前节点的引用指向待添加节点

def insert_at_middle(self, insert_node, data):
    """
    在insert_node节点后添加新节点
    :param insert_node:
    :param data:
    :return:
    """
    new_node = Node(data)
    new_node.reference = insert_node.reference
    insert_node.reference = new_node

从链表删除节点

A->B->C

A.reference = B

B.reference = C

C.reference = D

删除B节点,则需遍历链表,当到达指向节点B的节点A时,将该值替换为存储在节点B的指针值,节点A指向节点C, 节点B从链表删除

def remove_node(self, remove_obj):
    """
    删除remove_obj节点信息
    :param remove_obj:
    :return:
    """
    presentNode = self.head
    while presentNode:
        if presentNode.reference == remove_obj:
            presentNode.reference = remove_obj.reference
            break
        presentNode = presentNode.reference

三、双链表

双向链表包含3个部分,指向前一个节点指针、数据和指向下一个节点指针,如下图所示:
在这里插入图片描述

双向链表支持从前向后和从后向前遍历,从头开始,使用next移动到下一个节点,从尾开始,使用prev移动到上一个节点,代码如下所示

def recursiveAfter(self):
    """
    从后向前遍历
    :return:
    """
    presentNode = self.tail
    while presentNode.prev:
        print("从前向后遍历,当前值value=", presentNode.data)
        presentNode = presentNode.prev

def recursiveFront(self):
    """
    从后向前遍历
    :return:
    """
    presentNode = self.head
    while presentNode:
        print("从后向前遍历,当前值value=", presentNode.data)
        presentNode = presentNode.next

双向链表尾部追加节点,需要确保追加节点的prev指针指向上一个节点信息

def appendNode(self, data):
    """
    在尾部添加节点
    :param data:
    :return:
    """
    new_data = Node(data)
    presentNode = self.head
    while presentNode:
        presentNode = presentNode.next
    presentNode.next = new_data
    new_data.prev = presentNode

删除节点信息,需要遍历双向链表两次,首先从链表头部开始使用next向后遍历,遇到删除对象,将当前节点的next更改为删除对象之后的节点,同时从后向前遍历,再次遇到删除对象,将当前节点的prev值更改为其之前的节点

def removeNode(self, removeObj):
    """
    删除节点需要遍历两边链表
    :param removeObj:
    :return:
    """
    presentNode = self.head
    # 从前向后删除
    while presentNode:
        if presentNode.next == removeObj:
            presentNode.next = removeObj.next
            break
        presentNode = presentNode.next
    # 从后向前删除
    presentNodeTail = self.tail
    while presentNodeTail:
        if presentNodeTail.prev == removeObj:
            presentNodeTail.prev = removeObj.prev
            break
        presentNodeTail = presentNodeTail.prev

四、反向链表

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

反向列表的实现思路是

  • 保存上一个节点的节点信息

  • 反转节点指向,将当前节点的next指向上一个节点,比如原链表:1->2->3时,应改为3->2->1->NULL

  • 继续处理后面的节点

    如下图所示
    在这里插入图片描述

代码实现思路,如下所示

def reverse(self):
    """
    1->2->3->None
    3->2->1->None
    :return:
    """
    previous = None
    # 头节点
    presentNode = self.head
    # 下一个节点信息
    while presentNode:
        # 获取下一个节点
        nextVal = presentNode.reference
        # 将当前节点的next指向上一个节点
        presentNode.reference = previous
        previous = presentNode
        presentNode = nextVal
    # 最后一个节点赋值为头节点
    self.head = previous
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值