单链表之python实现学习笔记及环形链表-反转链表

一、单链表定义

单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素
链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。

二、python实现

用python实现单链表操作,包括创建、遍历、增添、删除,代码如下:

class Node(object):
    """节点"""

    def __init__(self, elem):
        self.elem = elem
        self.next = None  # 初始设置下一节点为空

'''
上面定义了一个节点的类,当然也可以直接使用python的一些结构。比如通过元组(elem, None)
'''

# 下面创建单链表,并实现其应有的功能
class SingleLinkList(object):
    """单链表"""

    def __init__(self, node=None):  # 使用一个默认参数,在传入头结点时则接收,在没有传入时,就默认头结点为空
        self.__head = node

    def is_empty(self):
        '''链表是否为空'''
        return self.__head == None

    def length(self):
        '''链表长度'''
        # cur游标,用来移动遍历节点
        cur = self.__head
        # count记录数量
        count = 0
        while cur != None:
            count += 1
            cur = cur.next
        return count

    def travel(self):
        '''遍历整个列表'''
        cur = self.__head
        while cur != None:
            print(cur.elem, end=' ')
            cur = cur.next
        print("\n")

    def add(self, item):
        '''链表头部添加元素'''
        node = Node(item)
        node.next = self.__head
        self.__head = node

    def append(self, item):
        '''链表尾部添加元素'''
        node = Node(item)
        # 由于特殊情况当链表为空时没有next,所以在前面要做个判断
        if self.is_empty():
            self.__head = node
        else:
            cur = self.__head
            while cur.next != None:
                cur = cur.next
            cur.next = node

    def insert(self, pos, item):
        '''指定位置添加元素'''
        if pos <= 0:
            # 如果pos位置在0或者以前,那么都当做头插法来做
            self.add(item)
        elif pos > self.length() - 1:
            # 如果pos位置比原链表长,那么都当做尾插法来做
            self.append(item)
        else:
            per = self.__head
            count = 0
            while count < pos - 1:
                count += 1
                per = per.next
            # 当循环退出后,pre指向pos-1位置
            node = Node(item)
            node.next = per.next
            per.next = node

    def remove(self, item):
        '''删除节点'''
        cur = self.__head
        pre = None
        while cur != None:
            if cur.elem == item:
                # 先判断该节点是否是头结点
                if cur == self.__head:
                    self.__head = cur.next
                else:
                    pre.next = cur.next
                break
            else:
                pre = cur
                cur = cur.next

    def search(self, item):
        '''查找节点是否存在'''
        cur = self.__head
        while not cur:
            if cur.elem == item:
                return True
            else:
                cur = cur.next
        return False
 
#测试
if __name__ == "__main__":
    # node = Node(100)  # 先创建一个节点传进去
    ll = SingleLinkList()
    print(ll.is_empty())
    print(ll.length())

    ll.append(3)
    ll.add(999)
    ll.insert(-3, 110)
    ll.insert(99, 111)
    print(ll.is_empty())
    print(ll.length())
    ll.travel()
    ll.remove(111)
    ll.travel()

三、编程题

1、142 环形链表Ⅱ

  • 题目
    给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
    为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
    说明:不允许修改给定的链表。

  • 示例 :
    输入:head = [3,2,0,-4], pos = 1
    输出:tail connects to node index 1
    解释:链表中有一个环,其尾部连接到第二个节点。

  • 思路一
    创建两个节点,第一个慢节点单步走,第二个快节点两步走,如果没有环,则快节点会首先走到链表尾,退出循环,返回False。如果存在环,则快节点会再第二圈或者第三圈的地方追上慢节点,直到两者相等,则返回True。
    可以发现,快节点是慢节点的多少倍,快节点就通过多少圈与慢节点相遇。
    所以就根据相遇点距环入口的距离等于头节点距环入口的距离。

  • 代码如下

class Solution(object):
    def detectCycle(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if head is None or head.next is None :
            return None
        slow = fast = head
        while fast.next and fast.next.next:
            slow = slow.next
            fast = fast.next.next
            if slow == fast:
                m = head
                while slow != m:
                    m = m.next
                    slow = slow.next
                return m
        return None

-运行结果
在这里插入图片描述

  • 思路二
    采用哈希表的思想,创建一个空字典,若下一个能在字典里找到,则返回,并且重复的元素的值作为入环的第一个节点。
  • 代码如下
class Solution(object):
    def detectCycle(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        node_dict = {}        
        temp = head        
        n = 0
        while temp:
            node_dict[temp]=n
            temp = temp.next
            if temp in node_dict:
                return temp
            n = n + 1
        return None

-运行结果
在这里插入图片描述

2、206反转链表

  • 题目
    反转一个单链表。

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

  • 思路
    迭代法,从前往后遍历链表,定义三个指针分别指向相邻的三个结点,反转前两个结点,即让第二个结点指向第一个结点。然后依次往后移动指针,直到第二个结点为空结束,再处理链表头尾即可。

  • 代码如下

class Solution(object):
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if head is None:
            return None
        cur = head
        pre = None
        nxt = cur.next
        while nxt:
            cur.next = pre
            pre = cur
            cur = nxt
            nxt = nxt.next
        cur.next = pre
        head = cur
        return head
  • 运行结果
    在这里插入图片描述

部分内容参考:
https://www.cnblogs.com/yudanqu/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值