2 to the nth power merge sort

principle

        In general recursive sorting, each recursion divides the current list into two lists according to the middle value of the current list length, and ends the recursion when the length of the current list is 1. Now we will use a different splitting method to merge sort, assuming that the length of the list to be sorted is x. The first sort divides the list into lists x\div 2^{0}. The first and second lists compare the element sizes, the third and fourth lists compare the element sizes, the fifth and sixth lists compare the element sizes, and so on. After the comparison is completed, according to the size order of the comparison, the smaller elements are ranked first, and the larger elements are ranked last, forming a new list. The second time, the partially sorted new list is divided into x\div 2^{1}lists, and the previous comparison and sorting process is repeated to obtain a new list. The third time, the partially sorted new list is divided into x\div 2^{2}lists, and then the previous comparison and sorting process is repeated to obtain a new list. It ends when the nth power of 2 is greater than or equal to x. At this time we will get a list sorted from small to large.

Complete code

        Through the above principles we can design the following code:

def merge_sort_2n(list_: list):
    """
    2的n次方归并排序

    :param list_: 需要排序的列表
    :return: 排序后的列表
    """
    n = 0  # 设置n的初始值为0
    max_index = int(len(list_) / 2) if len(list_) % 2 == 0 else len(list_) // 2 + 1
    while len(list_) > 2 ** n:  # 当2的n次方大于等于需要排序列表的长度时,结束循环
        step = 2 ** n  # 创建一个步长值
        result = []  # 创建一个中间列表来存储每次比较排序后的元素
        for i in range(0, max_index, step):  # 根据步长值来控制每次参与比较的元素个数
            list_a = list_[2 * i:2 * i + step]  # 通过切片把要参与比较的元素取出来变成一个新列表
            list_b = list_[2 * i + step:2 * (i + step)]  # 通过切片把要参与比较的元素取出来变成一个新列表
            pointer_a, pointer_b = 0, 0  # 设置两个索引下标
            while pointer_a < len(list_a) and pointer_b < len(list_b):  # 当有一个索引下标超出索引范围时,结束循环
                if list_a[pointer_a] < list_b[pointer_b]:  # 判断两个列表中相同索引位置的元素大小
                    result.append(list_a[pointer_a])  # 当列表list_a的元素比较小时,把list_a的当前索引元素放到result列表中
                    pointer_a += 1  # list_a的索引下标加一
                else:
                    result.append(list_b[pointer_b])  # 当列表list_b的元素比较小时,把list_b的当前索引元素放到result列表中
                    pointer_b += 1  # list_b的索引下标加一
            result += list_a[pointer_a:]  # 把list_a中剩余的元素并入result后面,可能是空列表
            result += list_b[pointer_b:]  # 把list_b中剩余的元素并入result后面,可能是空列表
        print(result)  # 打印出每次排序后的列表
        list_ = result  # 把排序后的列表重新赋值给list_
        n += 1  # 循环一次后n的值加一
    return list_  # 返回排序后的列表

Dynamic display

        We can use the tkinter graphical interface to dynamically display the 2 nth power merge sorting process. The code is as follows:

import threading
import time
import tkinter as tk

index = []


class MergeSort2n:
    """
    2的n次方归并排序动态展示\n
    使用tkinter中的方法创建UI界面
    """

    def __init__(self, list_: list):
        """
        UI界面窗口初始化\n
        :return:
        """
        self.list = list_
        root = tk.Tk()
        root.title('2的n次方归并排序')
        width = 800
        height = 500
        win_width = root.winfo_screenwidth()
        win_height = root.winfo_screenheight()
        x = win_width / 2 - width / 2
        y = win_height / 2 - height / 2
        root.geometry('%dx%d+%d+%d' % (width, height, x, y))
        self.canvas = tk.Canvas(root, bg="#FFFFFF", width=800, height=500)
        self.canvas.grid(row=1, column=0, rowspan=10, columnspan=10)
        self.display_list()
        self.thread_ui()
        root.mainloop()

    def display_list(self):
        """
        画出需要排序的列表,并把组件id放入index列表中\n
        :return:
        """
        n = 0
        for i in self.list:
            id_ = self.canvas.create_rectangle(60 * n + 140, 400, 60 * n + 170, 400 - 30 * i, fill='#5B9BD6')
            index.append(id_)
            n += 1

    def update_display(self, origin: list, now: list):
        """
        更新界面显示\n
        :param origin: 需要更新的位置索引
        :param now: 索引对应部分的新值
        :return:
        """
        time.sleep(1)
        for i in origin:
            self.canvas.itemconfigure(index[i], fill='#00B005')
        time.sleep(1)
        for i in range(len(origin)):
            self.canvas.coords(index[origin[i]], 60 * origin[i] + 140, 400, 60 * origin[i] + 170, 400 - 30 * now[i])
        for i in origin:
            self.canvas.itemconfigure(index[i], fill='#5B9BD6')

    def merge_sort_2n(self, list_: list):
        """
        2的n次方归并排序\n
        :param list_: 需要排序的列表
        :return: 
        """
        n = 0
        max_index = int(len(list_) / 2) if len(list_) % 2 == 0 else len(list_) // 2 + 1
        while len(list_) > 2 ** n:
            step = 2 ** n
            result = []
            for i in range(0, max_index, step):
                list_a = list_[2 * i:2 * i + step]
                list_b = list_[2 * i + step:2 * (i + step)]
                min_ = 2 * i
                max_ = 2 * (i + step) if 2 * (i + step) <= len(list_) else len(list_)
                pointer_a, pointer_b = 0, 0
                while pointer_a < len(list_a) and pointer_b < len(list_b):
                    if list_a[pointer_a] < list_b[pointer_b]:
                        result.append(list_a[pointer_a])
                        pointer_a += 1
                    else:
                        result.append(list_b[pointer_b])
                        pointer_b += 1
                result += list_a[pointer_a:]
                result += list_b[pointer_b:]
                self.update_display(list(range(min_, max_)), result[min_:max_])
            list_ = result
            n += 1

    def thread_ui(self):
        """
        多线程执行任务\n
        :return:
        """
        thread = threading.Thread(target=self.merge_sort_2n, args=(self.list, ))
        thread.setDaemon(True)
        thread.start()


if __name__ == '__main__':
    list1 = [6, 3, 9, 1, 4, 7, 2, 8, 5]
    MergeSort2n(list1)

The execution results are as follows:

Guess you like

Origin blog.csdn.net/qq_40148262/article/details/131185041