美文网首页
python链表及算法

python链表及算法

作者: 修行的修行 | 来源:发表于2021-03-02 14:05 被阅读0次

实现了python单向链表及一些算法题

from functools import wraps

class Node(object):
    def __init__(self,next_node=None,value=''):
        self.value = value
        self.next_node = next_node

class Chain(object):
    def __init__(self,head = None):
        self.head = head

    #  获取长度
    def get_length(self):
        length = 1
        assert (self.head)
        cur_node = self.head
        while cur_node.next_node:
            length+=1
            cur_node = cur_node.next_node
        return  length

    #  构建链表
    def create(self,list):
        assert (len(list)>0)
        self.head = Node(None,list[0])
        if len(list) == 1:
            return
        else:
            cur = self.head
            for i in list[1:]:
                cur.next_node = Node(None,i)
                cur = cur.next_node

    # 装饰器
    def show(name):
        def decorator(func):
            @wraps(func)
            def wrapper(self,*args, **kwargs):
                self._show()
                result = func(self,*args, **kwargs)
                self._show(name)
                print('\n')
                return result
            return wrapper
        return decorator

    #  遍历链表
    def _show(self,name='原链表'):
        assert (self.head)
        dummy_node = Node(self.head)
        cur_node = dummy_node
        print(name+':', end="")
        while cur_node.next_node:
            cur_node = cur_node.next_node
            print(str(cur_node.value) + '->', end="")
        print('None')
        del dummy_node

    #  翻转链表
    @show('翻转链表')
    def reverse(self):
        cur_node = self.head
        pre_node = None
        while cur_node:
            temp_node = cur_node.next_node
            cur_node.next_node = pre_node
            pre_node = cur_node
            cur_node = temp_node
        self.head = pre_node

    #  删除链表中第一个value为value的节点
    @show('删除第一个value')
    def remove_one(self,value):
        cur_node = self.head
        if cur_node.value==value:
            self.head = cur_node.next_node
            del cur_node
        else:
            while cur_node.next_node:
                if cur_node.next_node.value == value:
                    del_node = cur_node.next_node
                    cur_node.next_node = del_node.next_node
                    del  del_node
                    break
                else:
                    cur_node = cur_node.next_node


    #  删除链表中所有value为value的节点
    @show('删除所有value')
    def remove_all(self,value):
        cur_node = self.head
        while cur_node.value == value:
            cur_node = cur_node.next_node
            self.head = cur_node
        if cur_node.value==value and cur_node.next_node is None:
            self.head = cur_node.next_node
            del cur_node
        else:
            while cur_node.next_node:
                if cur_node.next_node.value == value:
                    del_node = cur_node.next_node
                    cur_node.next_node = del_node.next_node
                    del del_node
                else:
                    cur_node = cur_node.next_node

    #  根据给定的标记位置翻转链表
    def reverse_index(self,start,end):
        length = self.get_length()
        if start<=0 or end<=0 or end>length or start>length:
            raise Exception('错误的位置标记')
        if start == end:
            return
        n=0
        dumpy_node =  Node(self.head)
        unswaped_pre_node = dumpy_node
        self.head = dumpy_node
        cur_node = self.head
        while n < start and cur_node.next_node:
            n+=1
            unswaped_pre_node = cur_node   #标记未被交换位置的最前节点
            cur_node = cur_node.next_node
        swaped_pre_node = cur_node #标记被交换位置的最前节点
        post_node = cur_node.next_node
        while n < end:
            n+=1
            unswaped_post_node = post_node.next_node #标记未被交换位置的最后节点
            swaped_post_node = post_node #标记被交换位置的最后节点
            post_node.next_node = cur_node
            cur_node = post_node
            post_node = unswaped_post_node #不断更新最前的节点
        unswaped_pre_node.next_node = swaped_post_node
        swaped_pre_node.next_node = unswaped_post_node
        self.head = dumpy_node.next_node
        del dumpy_node

    #  去除有序链表的相同value节点
    @show('去除有序链表相同项')
    def set_sorted_chain(self):
        cur_node = self.head
        while cur_node and cur_node.next_node:
            if cur_node.value == cur_node.next_node.value:
                del_node = cur_node.next_node
                cur_node.next_node = del_node.next_node
                del  del_node
            else: #没有删除节点才向前移动节点
                cur_node = cur_node.next_node

    #  根据给定的x值,将链表分成2部分.左边小于x,右边大于等于x
    @show('链表分成两部分')
    def two_partition(self,x):
        dummy_node = Node(self.head)
        cur_node = dummy_node.next_node #创建一个虚假节点成为头节点
        #  先找到value为x的节点
        while cur_node:
            if cur_node.value == x:
                x_node = cur_node
                cur_node = cur_node.next_node
            else:
                cur_node = cur_node.next_node
        assert (x_node) # 如果不存在则表示x标记错误
        cur_node = dummy_node.next_node
        pre_x_node = None  # 接在x_node前的第一个节点
        post_x_node,flag = None,True # 接在x_node后的第一个节点,通过flag来绑定
        pre_min_node = dummy_node # 保存小于x_node节点的前一个节点
        pre_max_node = None # 保存大于x_node节点的前一个节点
        while cur_node:
            if cur_node.value < x:
                pre_min_node.next_node = cur_node
                pre_min_node = cur_node
                pre_x_node = cur_node
            elif cur_node.value > x:
                if flag:
                    post_x_node = cur_node
                    flag = False
                if pre_max_node is None:
                    pre_max_node = cur_node
                else:
                    pre_max_node.next_node = cur_node
                    pre_max_node = cur_node
            elif cur_node == x_node:
                pass
            cur_node = cur_node.next_node
        pre_max_node.next_node = None
        x_node.next_node = post_x_node
        pre_x_node.next_node = x_node
        self.head = dummy_node.next_node
        del dummy_node

    #  merge两个有序链表
    @show('merge两个有序链表')
    def merge(self,another_chain):
        assert (another_chain.head)
        cur_node = self.head
        cur_node1 = another_chain.head
        head_node = cur_node if cur_node.value<=cur_node1.value else cur_node1  #选出起始节点
        dummy_node = Node(head_node) #选出一个虚假的头节点
        tmp_node = dummy_node
        while cur_node or cur_node1:
            if not cur_node:
                tmp_node.next_node = cur_node1
                tmp_node = cur_node1
                cur_node1 = cur_node1.next_node
            elif not cur_node1:
                tmp_node.next_node = cur_node
                tmp_node = cur_node
                cur_node = cur_node.next_node
            elif cur_node.value <= cur_node1.value:
                tmp_node.next_node = cur_node
                tmp_node  = cur_node
                cur_node = cur_node.next_node
            else:  #  cur_node1.value < cur_node.value
                tmp_node.next_node = cur_node1
                tmp_node = cur_node1
                cur_node1 = cur_node1.next_node
        self.head = dummy_node.next_node
        del dummy_node

    #  判定链表是否为回文结构
    @show('判定是否为回文结构')
    def judge_palindrome(self):
        slow_node = self.head  # 每次走一步
        slow_index = 1
        fast_node = self.head   #每次走两步
        fast_index = 1
        if not slow_node.next_node: #只有一个头节点
            print('是回文结构')
            return  True
        while slow_node.next_node and fast_node.next_node:
            if not fast_node.next_node.next_node: # 偶数个节点
                fast_node = fast_node.next_node
                fast_index+=1
            else: # 奇数个节点
                slow_node = slow_node.next_node
                slow_index+=1
                fast_node = fast_node.next_node.next_node
                fast_index+=2
        self.reverse_index(slow_index+1, fast_index)
        flag_node = slow_node.next_node if fast_index % slow_index == 0 else slow_node  # slow_cur_node不能到达的节点
        slow_cur_node = self.head
        fast_cur_node = slow_node.next_node
        while slow_cur_node.next_node != flag_node:
            if slow_cur_node.value == fast_cur_node.value:
                slow_cur_node = slow_cur_node.next_node
                fast_cur_node = fast_cur_node.next_node
            else:
                print('不是回文结构')
                return
        print('是回文结构')


    # L(0) -> L(1) -> L(2) .... -> L(n-1) -> L(n)
    # L(0) -> L(n) -> L(1) .... -> L(n-1) -> L(2)
    #  逆序穿插链表
    @show('逆序穿插链表')
    def reorder_list(self):
        if not self.head.next_node:
            return
        slow_node = self.head  # 每次走一步
        slow_index = 1
        fast_node = self.head  # 每次走两步
        fast_index = 1
        while slow_node.next_node and fast_node.next_node:
            if not fast_node.next_node.next_node: # 偶数个节点
                fast_node = fast_node.next_node
                fast_index+=1
            else: # 奇数个节点
                slow_node = slow_node.next_node
                slow_index+=1
                fast_node = fast_node.next_node.next_node
                fast_index+=2
        pre_node = slow_node.next_node
        slow_node.next_node = None
        cur_node = pre_node.next_node
        pre_node.next_node = None
        while cur_node:
            later_node = cur_node.next_node
            cur_node.next_node = pre_node
            pre_node = cur_node
            cur_node = later_node
        node1 = self.head
        node2 = pre_node
        dummy_node = Node(node1)  #选出一个虚假的头节点
        tmp_node = dummy_node
        n = 1
        while node1 or node2:
            if n%2==1 and node1:
                tmp_node.next_node = node1
                tmp_node = node1
                node1 = node1.next_node  if node1.next_node else None
                n =2
            elif n%2==0 and node2:
                tmp_node.next_node = node2
                tmp_node = node2
                node2 = node2.next_node if node2.next_node else None
                n =1
            elif node1:
                tmp_node.next_node = node1
                node1 = node1.next_node if node1.next_node else None
            elif node2:
                tmp_node.next_node = node2
                node2 = node2.next_node if node2.next_node else None
        del dummy_node

    #给定一个链表,让这个链表向右旋转K位,其中k为非负数
    #如:  1>2>3>4>5>NULL k = 2
    #第一次旋转: 5>1>2>3>4>NULL
    #第二次旋转: 4>5>1>2>3>NULL
    @show('旋转链表')
    def rotate_list(self,k):
        assert (k>=0)
        chain_length = self.get_length()
        real_k = k % chain_length
        if real_k == 0: return
        slow_node = self.head
        fast_node = self.head
        while real_k>0 and fast_node.next_node:
            fast_node = fast_node.next_node
            real_k-=1
        while fast_node.next_node:
            fast_node = fast_node.next_node
            slow_node = slow_node.next_node
        fast_node.next_node = self.head
        self.head = slow_node.next_node
        slow_node.next_node = None

        # 给定一个链表,让这个链表向右旋转K位,其中k为非负数
        # 如:  1>2>3>4>5>NULL k = 2
        # 第一次旋转: 5>1>2>3>4>NULL
        # 第二次旋转: 4>5>1>2>3>NULL

    #如: 1>2>3>4>5>NULL,k=2
    #返回: 1>2>3>5>NULL
    @show('倒数k数删除链表')
    def romove_node_from_end(self, k):
        assert (k>0)
        slow_node = Node(self.head)
        del_node = self.head
        fast_node = self.head
        cur_index = 1
        while cur_index<k and fast_node.next_node:
            fast_node = fast_node.next_node
            cur_index+=1
        if cur_index!=k:
            print('k值超过了链表长度')
            return
        if not fast_node.next_node:
            self.head = self.head.next_node
            del del_node
            return
        while fast_node.next_node:
            slow_node = slow_node.next_node
            del_node = del_node.next_node
            fast_node = fast_node.next_node
        slow_node.next_node = del_node.next_node
        del del_node

    #给定一个链表,每k个节点为一组,反转每一组的k个节点.k为正整数且小于等于链表长度.如果链表长度不是k整数倍,剩余部分不需要反转.
    #如 1>2>3>4>5>NULL
    #若k=2,则结果为: 2>1>4>3>5>NULL
    #若k=3,则结果为: 3>2>1>4>5>NULL
    @show('根据K值反转链表')
    def reverse_nodes_in_kgroup(self,k):
        assert (k>=1)
        cur_node = self.head
        n = 1 #当前轮次进行到的节点
        cur_n = 1  #当前行进到了节点
        while cur_node.next_node:
            while n<k and cur_node:
                cur_node = cur_node.next_node
                n+=1
                cur_n+=1
            if n==k:
                cur_node = cur_node.next_node
                self.reverse_index(cur_n - 2, cur_n)
                if not cur_node:
                    return
                n = 1
                cur_n += 1
            else: #意味着到底部了
                return




chain = Chain()

#  删除第一个指定value
x=[1,4,5,4,5,6,7,1,1,3]
chain.create(x)
chain.remove_one(1)
#  删除所有指定value
x=[1,1,1,4,5,4,5,6,7,1,1,3]
chain.create(x)
chain.remove_all(1)
#  翻转链表
x=[1,1,1,4,5,4,5,6,7,1,1,3]
chain.create(x)
chain.reverse()
# 去除有序链表的相同value节点
x=[1,1,1,3,3,4,4]
chain.create(x)
chain.set_sorted_chain()
#  根据给定的x值,将链表分成2部分.左边小于x,右边大于等于x
x=[1,1,1,4,5,4,5,6,7,1,1,3]
chain.create(x)
chain.two_partition(3)
#  将两个有序链表merge
x=[1,3,5,7]
y=[0,2,4,6,8]
chain.create(x)
chain1 = Chain()
chain1.create(y)
chain.merge(chain1)
#  判定是否为回文结构
x=[1,2,3,4,5,4,3,2,1]
chain.create(x)
chain.judge_palindrome()
#  逆序穿插链表
x=[1,2,3,4,5,6,7,8,9]
chain.create(x)
chain.reorder_list()
#  旋转链表
x=[1,2,3,4,5,6,7,8,9]
chain.create(x)
chain.rotate_list(3)
#  倒数k数删除链表
x=[1,2,3,4,5,6,7,8,9]
chain.create(x)
chain.romove_node_from_end(9)
#  根据K值反转链表
x=[1,2,3,4,5,6,7,8,9]
chain.create(x)
chain.reverse_nodes_in_kgroup(3)

output:
原链表:1->4->5->4->5->6->7->1->1->3->None
删除第一个value:4->5->4->5->6->7->1->1->3->None


原链表:1->1->1->4->5->4->5->6->7->1->1->3->None
删除所有value:4->5->4->5->6->7->3->None


原链表:1->1->1->4->5->4->5->6->7->1->1->3->None
翻转链表:3->1->1->7->6->5->4->5->4->1->1->1->None


原链表:1->1->1->3->3->4->4->None
去除有序链表相同项:1->3->4->None


原链表:1->1->1->4->5->4->5->6->7->1->1->3->None
链表分成两部分:1->1->1->1->1->3->4->5->4->5->6->7->None


原链表:1->3->5->7->None
merge两个有序链表:0->1->2->3->4->5->6->7->8->None


原链表:1->2->3->4->5->4->3->2->1->None
是回文结构
判定是否为回文结构:1->2->3->4->5->1->2->3->4->None


原链表:1->2->3->4->5->6->7->8->9->None
逆序穿插链表:1->9->2->8->3->7->4->6->5->None


原链表:1->2->3->4->5->6->7->8->9->None
旋转链表:7->8->9->1->2->3->4->5->6->None


原链表:1->2->3->4->5->6->7->8->9->None
倒数k数删除链表:2->3->4->5->6->7->8->9->None


原链表:1->2->3->4->5->6->7->8->9->None
根据K值反转链表:3->2->1->6->5->4->9->8->7->None

相关文章

网友评论

      本文标题:python链表及算法

      本文链接:https://www.haomeiwen.com/subject/ncpqqltx.html