数据结构noj单链表的归并_数据结构与算法之python归并排序(2)

8c0a17bf805856f7ea857f4679a6cd3c.png

前言

继上篇 数据结构与算法之python归并排序 的数组的实现,这篇谈谈如何用一个链表实现。

选择链表

链表有单链表、双链表、循环链表,但是应该选择哪个呢?是的双链表是你的最佳选择。你可以试一下如果使用单链表的话即只有一个头指针或者尾指针 能否实现归并排序。来看下代码吧

双链表

class LinkNode(object):
    """
    双链表,头指针删除节点,尾指针插入节点
    """
    class Empty(Exception):
        pass

    class _Node:
        __slots__ = '_element', '_next'

        def __init__(self, element, next):
            self._element = element
            self._next = next

    def __init__(self):
        self._head = None  # 头指针
        self._tail = None  # 尾指针
        self._size = 0  # 链表长度

    def __len__(self):
        """
        链表长度
        :return:
        """
        return self._size

    def is_empty(self):
        """
        判断链表是否为空
        :return:
        """
        return self._size == 0

    def add_node(self, data):
        """
        增加节点, 尾插法
        表长 +1
        :return:
        """
        new_node = self._Node(data, None)
        if self.is_empty():
            self._head = new_node  # 如果是空链表,新插入的链表头指针也需要变更
        else:
            self._tail._next = new_node  # 尾指针指向新的节点
        self._tail = new_node  # 尾指针后移
        self._size += 1

    def delete_node(self):
        """
        删除节点: 头删除法
        :return:
        """
        if self.is_empty():
            raise self.Empty('Link node is empty!')
        _data = self._head._element
        self._head = self._head._next
        self._size -= 1
        if self.is_empty():
            self._tail = None
        return _data

    def first_data(self):
        """
        首元素
        :return:
        """
        if self.is_empty():
            raise self.Empty('link node is empty!')
        return self._head._element

目前定义了双链表的结构,下面让我来看下归并排序的代码

归并排序

from functools import wraps


class MergeSortLinkNode(object):

    def __init__(self, func):
        wraps(func)(self)

    def __merge(self, left: LinkNode, right: LinkNode, res: LinkNode):
        """
        合并
        :param left:
        :param right:
        :param res:
        :return:
        """
        while not left.is_empty() and not right.is_empty():
            if left.first_data() < right.first_data():
                res.add_node(left.delete_node())
            else:
                res.add_node(right.delete_node())

        #  判断剩下的元素
        while not left.is_empty():
            res.add_node(left.delete_node())

        while not right.is_empty():
            res.add_node(right.delete_node())

    def __merge_sort(self, sqlist: LinkNode):
        """
        归并排序
        :param sqlist: 待排序的链表
        :return:
        """
        link_node_length = len(sqlist)  # 获取长度
        if link_node_length < 2:
            return
        mid = link_node_length // 2
        S1 = LinkNode()
        S2 = LinkNode()
        while len(S1) < mid:
            S1.add_node(sqlist.delete_node())
        while not sqlist.is_empty():
            S2.add_node(sqlist.delete_node())
        self.__merge_sort(S1)
        self.__merge_sort(S2)
        self.__merge(S1, S2, sqlist)

    def __call__(self, *args, **kwargs):
        res = self.__wrapped__(*args, **kwargs)
        self.__merge_sort(res)
        return res

这里我把归并排序定义为了一个类装饰器,想深入了解类装饰器的话,可以参考python3-cookbook 方面的信息

测试

import random

init_data = list()   # 初始化结果
test_result = LinkNode()  # 链表
print_res = list()  # 打印排序后的结果


@MergeSortLinkNode
def example():
    for i in range(10):
        _elem = random.randint(1, 50)
        init_data.append(_elem)
        test_result.add_node(_elem)
    return test_result

example()
while not test_result.is_empty():
    print_res.append(test_result.delete_node())
print('....init_data: ', init_data)
print('....print_res: ', print_res)

这里随机生成了10的长度,执行下结果,因为是随机执行的所以每次执行的结果都不一样,我这里的结果如下:

25b9a51b7e9ec2e9ee7a7a2e62cc824a.png

如果你比较细心的话,可能已经发现再双链表的封装的特性是一个队列。其实任何一种形式的基本队列都可以很容易地作为归并排序算法的容器类型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值