python数据结构之链表

1.功能实现

链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而顺序表相应的时间复杂度分别是O(logn)和O(1)。

特点:使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。

基本操作:包括创建链表(初始化)、获取长度、插入、查找、删除、遍历,以及略复杂的链表逆序和结点交换。下面将这些操作一一实现并作出解释。

class ListNode(object):
    def __init__(self,data,p = None):
        self.data = data
        self.next = p
 
class Linklist(object):
    def __init__(self):
        self.head = None
    def set(self):                        # 初始建立
        print('input:')
        data = input()
        if data != "":
            self.head = ListNode(int(data))
            p = self.head
        else:
            print('over!')
            return
        while 1:
            data = input()
            if data != "":
                p.next = ListNode(int(data))
                p = p.next
            else:
                print('over!')
                break
    @property
    def show(self):                        # 遍历链表
        print('链表元素如下:')
        p = self.head
        if p == None:
            print('Empty!')
            return
        while  p:
            print(p.data,end=',')
            p = p.next
        print('over!')
        return
    @property
    def isempty(self):                        # 判断是否空
        p = self.head
        if p == None:
            return True
        else:
            return False
    @property
    def length(self):                        # 获取长度
        p = self.head
        l = 0
        while p:
            l += 1
            p = p.next
        return l
    def insert(self,data,pos):                # 数据插入
        if self.isempty and pos != 1:
            raise Exception('wrong position!')
        p = self.head
        if pos == 1:
            self.head = ListNode(data)
            self.head.next = p
        n = 2
        while n < pos and p.next != None:
            p = p.next
            n += 1
        if n == pos:
            tmp = p.next
            p.next = ListNode(data)
            p = p.next
            p.next = tmp
        elif n < pos:
            raise Exception('wrong position!')
 
    def delete(self,pos):                        # 删除操作
        p = self.head
        # 假设位置信息有效
        if pos == 1:
            return self.head.next
        for i in range(pos - 2):
            p = p.next
        p.next = p.next.next

2.倒数第k结点及链表合并

1)题目如下:输入一个链表,输出该链表中倒数第k个结点。

class ListNode(object):
    def __init__(self, x):
        self.val=x
        self.next=None
        
class Solution(object):
    def __init__(self, head, k):
        n=0
        p=head
        while p!=None:
            n+=1
            p=p.next
        if n<k:
            return None
        p=head
        m=1
        while m<n-k+1:
            m+=1
            p=p.next
        return p

2)题目如下:输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

class ListNode:
    def __init__(self, x):
        self.x=x
        self.next=None
        
class Solution:
    def merge(self, pHead1, pHead2):
        if pHead1 is None:
            return pHead2
        if pHead2 is None:
            return pHead1
        
        if pHead1.val<=pHead2.val:
            pHead1.next=merge(pHead1.nextm pHead2)
        else:
            pHead2.next=merge(pHead1, pHead2.next)
            

3.链表右移/链表分割/链表逆序

1).  61. Rotate List (将链表右移K个位置)

Given a list, rotate the list to the right by k places, where k is non-negative.
Example:
Given 1->2->3->4->5->NULL and k = 2,

return 4->5->1->2->3->NULL.

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
 
class Solution:
    def rotateRight(self, head, k):
        """
        :type head: ListNode
        :type k: int
        :rtype: ListNode
        """
        
        if head == None:
            return None
        length = 1
        p = head 
        while p.next:
            p = p.next
            length += 1
        if k == length:
            return head
        elif k > length:
            k = k%length
        cn = 1
        q = head
        while cn < (length-k):
            q = q.next
            cn += 1
        p.next = head
        newhead = q.next
        q.next = None
        return newhead

2.  86. Partition List(链表分割)

Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x.You should preserve the original relative order of the nodes in each of the two partitions.

For example,
Given 1->4->3->2->5->2 and x = 3,

return 1->2->2->4->3->5.
 

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
 
class Solution:
    def partition(self, head, x):
        """
        :type head: ListNode
        :type x: int
        :rtype: ListNode
        """
        if head == None:
            return head
        p1 = ListNode(-1)
        p2 = ListNode(-1)
        h1, h2 = p1, p2
        while head:
            if head.val <x:
                p1.next = head
                p1 = p1.next
            else:
                p2.next = head
                p2 = p2.next
            head = head.next
        p2.next = None
        p1.next = h2.next
        return h1.next

3).  92. Reverse Linked List II(链表逆序)

class Solution:
    def reverseBetween(self, head, m, n):
        """
        :type head: ListNode
        :type m: int
        :type n: int
        :rtype: ListNode
        """
        if head == None:
            return head
        elif m == n:
            return head
        new = ListNode(-1)
        new.next = head
        head = new
        
        p = head       
        pre = head
        for i in range(m):
            pre = p
            p = p.next
        q = p
        for i in range(n-m):
            q = q.next
 
        # reverse
        pre_p = q.next
        cur = p
        for i in range(n-m+1):
            h = cur
            tmp = cur.next
            cur.next = pre_p
            pre_p = cur
            cur = tmp            
        pre.next = q        
        return head.next

4.移除重复项及带随机指针的链表复制

1)82. Remove Duplicates from Sorted List II (从有序列表中移除重复项)

Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list.
For example,
Given 1->2->3->3->4->4->5, return 1->2->5.

Given 1->1->1->2->3, return 2->3.

1)82. Remove Duplicates from Sorted List II (从有序列表中移除重复项)

Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list.
For example,
Given 1->2->3->3->4->4->5, return 1->2->5.

Given 1->1->1->2->3, return 2->3.
 

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
 
class Solution:
    def deleteDuplicates(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if head == None or head.next == None:
            return head        
        fhead = ListNode(0)
        fhead.next = head
        pre = fhead        
        cur = head
        
        while cur:
            while cur.next and cur.val==cur.next.val:
                cur = cur.next
            if pre.next == cur:          # 如果只此一个值,不删除,pre后移
                pre = cur
            else:
                pre.next = cur.next      # 如果不只一个,删除这些结点,pre暂不后移
            cur = cur.next
        return fhead.next

2)138. Copy List with Random Pointer(复制含有随机指针的链表)

# Definition for singly-linked list with a random pointer.
# class RandomListNode(object):
#     def __init__(self, x):
#         self.label = x
#         self.next = None
#         self.random = None
 
class Solution(object):
    def copyRandomList(self, head):
        """
        :type head: RandomListNode
        :rtype: RandomListNode
        """
        if head == None:
            return None
        p = head        
        while p:
            tmp = p.next
            p.next = RandomListNode(p.label)
            p.next.next = tmp
            p = tmp
        p = head
        while p:
            if p.random:
                p.next.random = p.random.next
            p = p.next.next
        newhead = RandomListNode(0)
        p = head
        q = newhead
        while p:
            tmp = p.next.next
            q.next = p.next
            q = q.next
            p.next = tmp
            p = tmp
        return newhead.next

5.带环链表及交叉链表(双指针法)

1)160.Intersection of Two Linked Lists 两链表交叉

Write a program to find the node at which the intersection of two singly linked lists begins.For example, the following two linked lists:
A:              a1 → a2
                             ↘
                                 c1 → c2 → c3
                             ↗            
B:     b1 → b2 → b3
begin to intersect at node c1.
Notes:
If the two linked lists have no intersection at all, return null.
The linked lists must retain their original structure after the function returns.
You may assume there are no cycles anywhere in the entire linked structure.

Your code should preferably run in O(n) time and use only O(1) memory.
 

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        p1, p2 = headA, headB
        while p1 is not p2:
            p1 = headB if not p1 else p1.next
            p2 = headA if not p2 else p2.next
        return p1

2)142. Linked List Cycle II 带环的链表

Given a linked list, return the node where the cycle begins. If there is no cycle, return null.
Note: Do not modify the linked list.

Follow up:Can you solve it without using extra space?

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None
 
class Solution(object):
    def detectCycle(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if head == None:
            return None
        pslow = head
        pfast = head
        k = 0
        while pfast.next and pfast.next.next:
            pslow = pslow.next
            pfast = pfast.next.next
            k += 1
            if pslow == pfast:
                break
        if pfast.next==None or pfast.next.next==None:
            return None
        # 确定有环,开始寻找
        p1 = head
        p2 = pslow
        while p1!=p2:
            p1 = p1.next
            p2 = p2.next
        return p1

猜你喜欢

转载自blog.csdn.net/weixin_42307828/article/details/84922543