zoukankan      html  css  js  c++  java
  • 单链表

    定义

    定义节点:数据域、指针域

    # 链表节点类
    class ListNode(object):
        def __init__(self, val):
            self.val = val
            self.next = None
    

    head指针指向的是第一个节点。

    定义单链表,及操作:

    # 链表节点类
    class ListNode(object):
        def __init__(self, val):
            self.val = val
            self.next = None
    
    # 链表类,生成链表以及定义相关方法
    class LinkList(object):
        # 生成链表,这里使用list来生成
        def create(self, valList):
            """
            :type valList: list
            :rtype: ListNode
            """
            node = ListNode(0)
            head = ListNode(0)
            head.next = node
            for i in range(len(valList)):
                node.next = ListNode(0)
                node.next.val = valList[i]
                node = node.next
            return head.next
    
        # 遍历显示
        def printLink(self, head):
            """
            :type head: ListNode
            :rtype: None
            """
            ans = head.next
            while ans:
                print(ans.val, end=' ')
                ans = ans.next
            # 回车换行
            print()
    
        # 链表判空
        def isEmpty(self, head):
            """
            :type head: ListNode
            :rtype: Boolean
            """
            # 若头指针为空,即链表为空,返回True; 否则返回False
            return True if not head else False
    
        # 取链表长度: 不算头结点
        def size(self, head):
            """
            :type head: ListNode
            :rtype: int
            """
            ans = head.next
            size = 0
            while ans:
                size += 1
                ans = ans.next
            return size
    
        # 根据索引取节点值域
        def getItem(self, head, index):
            """
            :type head: ListNode
            :type index: int
            :rtype: int
            """
            p = head.next
            count = 0
            while count != index:
                p = p.next
                count += 1
            return p.val
    
        # 根据索引设值
        def setItem(self, head, index, val):
            """
            :type head: ListNode
            :type index: int
            :type val: int
            :rtype: None
            """
            p = head
            count = -1
            while count < index - 1:
                p = p.next
                count += 1
            p.val = val
    
        # 单链表快速排序
        def quickSort(self, head):
            """
            :type head: ListNode
            :rtype: ListNode
            """
            if not head or not head.next:
                return head
            ans = ListNode(0)
            ans.next = head
            return self.sort(ans, None)
        def sort(self, head, end):
            if head == end or head.next == end or head.next.next == end:
                return head
            tpmHead = ListNode(0)
            # 划分节点
            poi = head.next
            # 遍历指针
            cur = poi
            pre = tpmHead
            # 一趟划分
            while cur.next != end:
                # 当前节点值域小于划分节点的值域,则将当前节点放到左侧
                if cur.next.val < poi.val:
                    pre.next = cur.next
                    pre = pre.next
                    cur.next = cur.next.next
                else:
                    cur = cur.next
            # 合并临时链表和原链表,将原链表接到临时链表后面即可
            pre.next = head.next
            head.next = tpmHead.next
            self.sort(head, poi)
            self.sort(poi, end)
            return head.next
    
        # 单链表归并排序
        def mergeSort(self, head):
            """
            :type head: ListNode
            :rtype: ListNode
            """
            if not head or not head.next:
                return head
            # 用快慢指针找链表中间节点,循环结束时:slow.next指向中间节点。
            slow, fast = head, head
            while fast.next and fast.next.next:
                slow = slow.next
                fast = fast.next.next
            # 对右半部分归并排序
            right = self.mergeSort(slow.next)
            # 断开左右两部分链表
            slow.next = None
            # 对左半部分归并排序
            left = self.mergeSort(head)
            return self.mergeLink(left, right)
        # 合并两个链表:按升序
        def mergeLink(self, left, right):
            node = ListNode(-1)
            head = node
            while left and right:
                if left.val < right.val:
                    node.next = left
                    left = left.next
                else:
                    node.next = right
                    right = right.next
                node = node.next
            node.next = left if left else right
            return head.next
    
    if __name__ == "__main__":
        # 数组/列表,存放链表节点的值域
        li = [4, 2, 5, 3, 7, 9, 1, 0]
        myLink = LinkList()
        # 生成单链表
        head = myLink.create(li)
        # 打印链表长度
        print("长度:", myLink.size(head))
        # 判空
        print("判空:", myLink.isEmpty(head))
        # 单链表快速排序(升序),不稳定排序算法
        ansQuick = myLink.quickSort(head)
        myLink.printLink(ansQuick)
        # 单链表归并排序(升序),稳定排序算法
        ansMerge = myLink.mergeSort(head)
        myLink.printLink(ansMerge)
    

    运行截图:


    特点

    单链表便于插入、删除,时间复杂度为O(1);不便于查找,时间复杂度为O(n)。

    Py和C实现链表的区别

    python是动态语言,可以直接把对象赋值给新的变量。

    在C/C++中,通常采用“指针+结构体”来实现链表;

    而在Python中,则可以采用“引用+类”来实现链表。

    如下图:

    mylist = Node()
    mylist.next = head
    

    head指针指向的是第一个节点。



    单链表头插法、尾插法

    设node是待插入节点。

    头插法:

    node.next = head.next
    head.next = node
    

    尾插法:

    while head.next:
    	head = head.next
    head.next = node
    

    头插法反转链表:

    #新链表的头指针
    pre = None
    while head:
    	#暂存头指针指向节点的下一个节点
    	temp = head.next
    	#断开原链表,头插法接到新链表
    	head.next = pre
    	pre = head
    	head = temp
    return pre
    

    在指定位置(第index个位置)插入节点:

    i = 0
    cur_node = self.head.next
    while i != index:
    	cur_node = cur_node.next
    	i += 1
    node.next = cur_node.next
    cur_node.next = node
    
    

    用“快慢指针”找单链表的中间节点

    # 用快慢指针找链表中间节点,循环结束时:slow.next指向中间节点。
    slow, fast = head, head
    while fast.next and fast.next.next:
        slow = slow.next
        fast = fast.next.next
    

    若快慢指针slow, fast初始为:slow, fast = head.next, head.next,则循环结束时,slow指向中间节点。

  • 相关阅读:
    leetcode-26-删除排序数组中的重复项
    用设计模式优化if else
    Builder设计模式
    退役划水(6)
    linux下安装nginx
    .NET 云原生架构师训练营(模块二 基础巩固 引入)--学习笔记
    SpringBoot项目的jar包瘦身计划
    如何解决高并发秒杀的超卖问题
    idea 最新jar包
    ArcGIS10.2企业数据库安装与配置
  • 原文地址:https://www.cnblogs.com/panweiwei/p/12856707.html
Copyright © 2011-2022 走看看