目录

python数据结构与算法

python数据结构与算法

python数据结构与算法

一 评判程序(算法)的优劣方法-时间复杂度

https://i-blog.csdnimg.cn/blog_migrate/c3f6c376de8d17c392f4473f035ee09c.png

https://i-blog.csdnimg.cn/blog_migrate/b3ffbe3f28b1e7a152a42546c881a8c3.png

https://i-blog.csdnimg.cn/blog_migrate/0ef770fb1c9d6a11b7b73cdee9f31409.png

二 数据结构的概念

https://i-blog.csdnimg.cn/blog_migrate/58857bea5c1b25c450bee8c97cd2cbab.png

https://i-blog.csdnimg.cn/blog_migrate/f64eb3fe64c274b240565511345b6035.png

https://i-blog.csdnimg.cn/blog_migrate/f0942d6097d99c546ca6fadcf1a56b00.png

https://i-blog.csdnimg.cn/blog_migrate/c3e4a142c25fbd2b09b22c73a7589c89.png

https://i-blog.csdnimg.cn/blog_migrate/f31c6572fb7f3b0f145fdac5a1a4b337.png

stmt参数:表示要进行测试的代码块语句

setup:运行代码块语句时所需的设置,比如从别的模块import

https://i-blog.csdnimg.cn/blog_migrate/661152655302f56c990f729794764a6c.png

from timeit import Timer

def test01():
    ls = []
    for i in range(1000):
        ls.append(i)
    return ls

def test02():
    ls = []
    for i in range(1000):
        ls += [i]
    return ls

def test03():
    ls = []
    return [i for i in range(1000)]

def test04():
    ls = list(range(1000))
    return ls

if __name__ == "__main__":
    timer = Timer('test01()','from __main__ import test01')
    t1 = timer.timeit(1000)
    print(t1)
    timer = Timer('test02()', 'from __main__ import test02')
    t2 = timer.timeit(1000)
    print(t2)
    timer = Timer('test03()', 'from __main__ import test03')
    t3 = timer.timeit(1000)
    print(t3)
    timer = Timer('test04()', 'from __main__ import test04')
    t4 = timer.timeit(1000)
    print(t4)

https://i-blog.csdnimg.cn/blog_migrate/4064d2f31520ba1212965f4ecfbe5e68.png

三 栈

3.1 栈的概念

https://i-blog.csdnimg.cn/blog_migrate/462bf107ddb1eec5488a673a1bebd256.png

https://i-blog.csdnimg.cn/blog_migrate/331a76472a739dfc47a881b785bda25b.png

https://i-blog.csdnimg.cn/blog_migrate/ee466ba95c80e4ea8e7b556e63efd837.png

3.2 将列表封装为一个栈

https://i-blog.csdnimg.cn/blog_migrate/b1d2befb28959ae810a5156a0b45160d.png

将列表的第0元素位置定义为栈底;将列表的第-1个元素的位置定义为栈顶

https://i-blog.csdnimg.cn/blog_migrate/097c2ff71294d4ba666c674e5f73c6b0.png

https://i-blog.csdnimg.cn/blog_migrate/a48520c9ecfdcfa0397c975edfe828bc.png

四 队列

4.1 队列的概念

https://i-blog.csdnimg.cn/blog_migrate/42189d2336c84c438aee21207560ae19.png

4.2 将列表封装为一个队列

https://i-blog.csdnimg.cn/blog_migrate/d853f853ad48c25bc27647ce2374fe24.png

https://i-blog.csdnimg.cn/blog_migrate/9b656e38791573615da4edb2b2ff8255.png

https://i-blog.csdnimg.cn/blog_migrate/f1e81541da39072014868aec178a7d3e.png

https://i-blog.csdnimg.cn/blog_migrate/66841e835953d7b4c4cc570530fcbe4a.png

结题思路
	由于是用队列来实现而队列的特性是先进先出即删除的元素一定是在队头位置的元素所以我们约定让手里有山芋的孩子永远排在对头
	当有山芋的孩子将山芋传递给下一个孩子时这个孩子被临时删除出队列然后重新入队列排到了队尾拿到山芋的孩子排到了对头
	到7秒时永久删除对头的孩子剩下的孩子排成一个新队列继续玩直到剩下最后一个孩子为止

https://i-blog.csdnimg.cn/blog_migrate/c1764a17be199ee69df9b3ee1e629439.png

class Queue():
    def __init__(self):
        self.ls = []
    def enqueue(self, item):
        self.ls.insert(0, item)

    def dequeue(self):
        return self.ls.pop()

    def isEmpty(self):
        return self.ls == []

    def size(self):
        return len(self.ls)

kids = ['A','B','C','D','E','F']
queue = Queue()
for kid in kids:
    queue.enqueue(kid)  # A在队头;F在队尾

while(queue.size()>1):
    for i in range(6):
        kid = queue.dequeue()
        queue.enqueue(kid)
    queue.dequeue()
print("获胜的是:%s"%queue.dequeue())

https://i-blog.csdnimg.cn/blog_migrate/2ab50eba01f8faed2e10bf47feda9cc7.png

五 双端队列

5.1 双端队列的概念

https://i-blog.csdnimg.cn/blog_migrate/0169c09a239d6380b0fdcd5c74c8021d.png

5.2 将列表封装为一个双端队列

https://i-blog.csdnimg.cn/blog_migrate/f33d71edc7ba65942e364294e0a935fb.png

class Deque():
    def __init__(self):
        self.items = []
    def addFront(self,item):
        self.items.insert(0,item)
    def addRear(self,item):
        self.items.append(item)
    def removeFront(self):
        return  self.items.pop(0)
    def removeRear(self):
        return self.items.pop()
    def isEmpty(self):
        return self.items == []
    def size(self):
        return len(self.items)

5.3 双端队列应用案例:回文检查

回文是一个字符串,读取首尾相同的字符,如madam

def isHuiWen(str1):
    q = Deque()
    for i in str1:
        q.addFront(i)
    res = True
    while(q.size()>1):
        if(q.removeFront() != q.removeRear()):
            res = False
            break
    return res

六 用两根队列实现一个栈

6.1 解题思路

https://i-blog.csdnimg.cn/blog_migrate/fdf62a7470948cc15e2d8e787d5482c9.png

6.2 代码

class Queue():
    def __init__(self):
        self.items=[]
    def enqueue(self,item):
        self.items.append(item)
    def dequeue(self):
        return self.items.pop(0)
    def travel(self):
        for item in self.items:
            print(item)
    def size(self):
        return len(self.items)


alist = [1,2,3,4,5]
q1 = Queue()
q2 = Queue()
for i in alist:
    q1.enqueue(i)

while q1.size() > 0:
    # 将q1中n-1个元素放入q2
    while q1.size() > 1:
        q2.enqueue(q1.dequeue())
    print(q1.dequeue())  # 栈弹出最后一个元素

    q1,q2 = q2,q1

七 顺序表

7.1 顺序表的概念

https://i-blog.csdnimg.cn/blog_migrate/69fa9966f25b825c68f285fafbe620d4.png

7.2 单数据类型顺序表的内存图

https://i-blog.csdnimg.cn/blog_migrate/cd333655e269f640cc089e7f5b21773f.png

6.3 多数据类型顺序表的内存图

https://i-blog.csdnimg.cn/blog_migrate/84e3b2fc35cd25b580c6cfa3b63d7179.png

八 链表

8.1 链表的概念

1. 顺序表的弊端顺序表的结构需要预先知道数据的大小来申请连续的内存空间而在扩充时又需要进行数据迁移
2. 相对于顺序表链表结构可以充分利用计算机的内存空间实现灵活的内存动态管理且进行扩充时不需要进行数据迁移
3. 链表是一种常见的基础数据结构是一种线性表但不想顺序表一样连续存储数据而是每一个节点里存放下一个节点的地址

8.2 链表的代码实现

https://i-blog.csdnimg.cn/blog_migrate/2f5748507cc422b53d541988ac2e2735.png

# 节点
class Node:
    def __init__(self, item):
        self.item = item
        self.next = None
# 节点
class Node:
    def __init__(self, item):
        self.item = item
        self.next = None

class Link():
    def __init__(self):
        self.__head = None
    def add (self, item):
        #新建一个节点
        node = Node(item)
        node.next = self.__head
        self.__head = node

    def append(self, item):
        #新建一个节点
        node = Node(item)
        if self.__head == None:
            self.__head = node
        else:
            cursor = self.__head
            while(cursor):
                prev = cursor
                cursor = cursor.next
            prev.next = node

    def insert(self, pos, item):
        # 新建一个节点
        node = Node(item)
        cursor = self.__head
        for i in range(pos):
            prev = cursor
            cursor = cursor.next
        prev.next = node
        node.next = cursor

    def travel(self):
        cursor = self.__head
        while(cursor):
            print(cursor.item)
            cursor = cursor.next

    def isEmpty(self):
        return self.__head == None

    def length(self):
        cursor = self.__head
        num = 0
        while(cursor):
            num+=1
            cursor = cursor.next
        return num

    def search(self, item):
        find = False
        cursor = self.__head
        while (cursor):
            if cursor.item == item:
                find = True
                break
            cursor = cursor.next
        return find

    def remove(self,item):
        cursor = self.__head
        if cursor.item == item: #要删除的是第一个节点
            self.__head = cursor.next
        else:
            while cursor:
                if cursor.item == item:
                    prev.next = cursor.next
                    del cursor
                    break
                prev = cursor
                cursor = cursor.next

8.3 链表的逆序

    def reverse(self):
        cursor = self.__head
        prev = None
        next_node = cursor.next
        while cursor:
            cursor.next = prev
            prev = cursor
            cursor = next_node
            if cursor:
                next_node = cursor.next
        self.__head = prev

九 二叉树

9.1 概念

https://i-blog.csdnimg.cn/blog_migrate/26c81deb1233e3950c5fd551005f0967.png

9.2 二叉树代码实现

class Node:
    def __init__(self, item):
        self.item = item
        self.left = None
        self.right = None

class Tree:
    def __init__(self):
        self.root = None

    def addNode(self,item):
        node = Node(item)
        # 如果要插入的节点是二叉树的第一个节点
        if self.root == None:
            self.root = node
            return
        # 如果要插入的节点不是二叉树的第一个节点
        cursor = self.root
        q = [cursor]

        while 1:
            check_node = q.pop(0)
            # 检查被检查节点的左节点是不是None。如果是就把新节点插入;如果不是则把左节点放入q列表待检查
            if check_node.left == None:
                check_node.left = node
                return
            else:
                q.append(check_node.left)
            # 检查被检查节点的右节点是不是None。如果是就把新节点插入;如果不是则把右节点放入q列表待检查
            if check_node.right == None:
                check_node.right = node
                return
            else:
                q.append(check_node.right)

    def travel(self):
        cursor = self.root
        q = [cursor]
        while q:
            check_node = q.pop(0)
            print(check_node.item)
            if check_node.left == None:
                pass
            else:
                q.append(check_node.left)
            if  check_node.right == None:
                pass
            else:
                q.append(check_node.right)

9.3 二叉树的遍历

9.3.1 广度优先遍历

一层一层对节点遍历

https://i-blog.csdnimg.cn/blog_migrate/301c15c914bcaad707ab0e15a1fae5be.png

    def travel(self):
        cursor = self.root
        q = [cursor]
        while q:
            check_node = q.pop(0)
            print(check_node.item)
            if check_node.left == None:
                pass
            else:
                q.append(check_node.left)
            if  check_node.right == None:
                pass
            else:
                q.append(check_node.right)

9.3.2 深度优先遍历

9.3.2.1 三种深度遍历类型
  1. 前序(子树中先遍历根):根左右
  2. 中序(子树中第二遍历根):左根右
  3. 后序(子树中最后遍历根):左右根

https://i-blog.csdnimg.cn/blog_migrate/3ec5d23b00ccf44718f18dbc16e38f59.png

9.3.2.2 深度遍历思路

二叉树中每一个节点都是某个子树的根节点,因此先以第一个子树写遍历的函数(根作为形参),然后在函数中将左、右节点作为新子树的根节点递归调用函数(左、右节点作为形参)

9.3.2.3 三种深度遍历代码实现
    def forward(self,root):  #前序遍历  根左右
        if root == None:
            return
        print(root.item)
        self.forward(root.left)
        self.forward(root.right)

    def middle(self,root):  #中序遍历   左根右
        if root == None:
            return
        self.middle(root.left)
        print(root.item)
        self.middle(root.right)

    def back(self,root):  #后序遍历  左右根
        if root == None:
            return
        self.back(root.left)
        self.back(root.right)
        print(root.item)

9.3.3 排序二叉树

9.3.3.1 排序二叉树概念
1. 利用二叉树可以对一个乱序数组排序
2. 需要先将乱序数组中的元素依次插入二叉树插入时要遵从一个准测第一个元素作为二叉树的根后序插入的元素如果比根节点小则插入根节点的左侧如果比根节点大则插入根节点的右侧
3. 对遵从上面准测插入的二叉树进行深度优先中序遍历后就是有序数组

https://i-blog.csdnimg.cn/blog_migrate/a3f5cc4b6a7f5a939be41a50d29a0672.png

9.3.3.2 排序二叉树插入数据思路
1. 使用一个cur游标作为当前节点开始时cur指向二叉树的根
2. 判断要插入的元素的值比根目前cur就是根的值大还是小
3. 如果比根小则是向左节点插入先判断根目前cur是根的左节点(cur.left)是不是空None如果是空则直接插入cur的左节点然后return结束如果不是空None则将cur的指向偏移到cur.left,等待之后和cur节点的左节点再做比较
4. 如果比根大则是向右节点插入先判断根目前cur是根的右节点(cur.right)是不是空None如果是空则直接插入cur的右节点然后return结束如果不是空None则将cur的指向偏移到cur.right,等待之后和cur节点的右节点再做比较
5. 在第3步和第4步中已经把当前节点cur做了偏移用一个while循环把步骤3和4包起来循环执行直到找到插入位置return为止
9.3.3.3 排序二叉树代码实现
class Node:
    def __init__(self, item):
        self.item = item
        self.left = None
        self.right = None

class SortTree:
    def __init__(self):
        self.root = None

    def addNode(self,item):
        node = Node(item)
        cur = self.root
        # 当要加入的节点是二叉树第一个节点时
        if(self.root == None):
            self.root = node
            return
        # 当要加入的节点不是二叉树第一个节点时
        while cur:
            ## 如果要加入的节点值小于根节点的值,则插入左节点
            if(node.item < cur.item):
                if(cur.left == None):
                    cur.left = node
                    return
                else:
                    cur = cur.left

            ## 如果要加入的节点值大于根节点的值,则插入右节点
            elif (node.item > cur.item):
                if(cur.right == None):
                    cur.right = node
                    return
                else:
                    cur = cur.right


    def middle(self,root):  #中序遍历   左根右
        if root == None:
            return
        self.middle(root.left)
        print(root.item)
        self.middle(root.right)



tree = SortTree()
alist = [3,8,5,7,6,2,9,4,1]
for i in alist:
    tree.addNode(i)
tree.middle(tree.root)

https://i-blog.csdnimg.cn/blog_migrate/4e3bdfb75fc142ff5d15f82531782f4e.png

十 二分查找法

10.1 概念

二分查找法一定是基于有序集合的查找;

10.2 代码

普通方法

alist = [1,2,3,4,5,6,7,8,9,10]
def find(lst, item):
    find = False
    first = 0;
    last = len(lst)-1

    while first<=last:
        middle = (first+last)//2
        if lst[middle]>item:
            last = middle-1
        elif lst[middle]<item:
            first=middle+1
        else:
            find = True
            break
    return find

递归法

alist = [1,2,3,4,5,6,7,8]
def find(lst, item, first=0, last=None):
    if last == None:
        last = len(lst)-1
    if first > last:
        return -1
    else:
        middle = (first + last) // 2
        if lst[middle] == item:
            return middle
        elif lst[middle]>item:
            return find(lst, item, first, middle-1)
        else:
            return find(lst, item, middle+1, last)

十一 排序算法

11.1 冒泡排序

11.1.1 原理

列表元素两两相比,每次比较大的值向后移动

https://i-blog.csdnimg.cn/blog_migrate/e96adfce8efeee63187d6ca987618975.png

11.1.2 分步实现代码

  1. 第一步:第一轮排序,将最大值冒泡到列表的最后位置
alist = [3,8,5,7,6]
def sort(alist):
    for index in range(len(alist)-1):
        if alist[index] > alist[index+1]:
            alist[index], alist[index+1] = alist[index+1], alist[index]
    return alist

print(sort(alist))

https://i-blog.csdnimg.cn/blog_migrate/a796dc5b96acc99474c3ef172b955818.png

  1. 第二步:一共需要n-1轮这样的冒泡才能排序完
alist = [3,8,5,7,6]
def sort(alist):
    for turn in range(len(alist)-1):
        for index in range(len(alist)-turn-1):
            if alist[index] > alist[index+1]:
                alist[index], alist[index+1] = alist[index+1], alist[index]
    return alist

print(sort(alist))

11.2 选择排序

11.2.1 原理

先假设第0个位置上的元素就是最大值(max_index=0);两两元素相比,哪个位置的元素大就将max_index改为那个位置的index;等所有元素都比较完后,将max_index位置那个元素和最后的元素换位置,即将最大值放到最后了

https://i-blog.csdnimg.cn/blog_migrate/7c8f1e4ebdd4927fc097372bf8f73c9c.png

11.2.2 分步实现代码

  1. 第一步:第一轮排序,将最大值max_index上的元素和最后位置的元素交换位置
alist = [3,8,5,7,6]
def sort(alist):
    max_index = 0
    for index in range(1,len(alist)):
        if alist[index] > alist[max_index]:
            max_index = index
    alist[max_index], alist[len(alist)-1] = alist[len(alist)-1], alist[max_index]
    return alist

print(sort(alist))

https://i-blog.csdnimg.cn/blog_migrate/fb760ca44ab55ceebbdb41498c561ebe.png

  1. 第二步:一共需要n-1轮这样的位置交换才能排序完
alist = [3,8,5,7,6]
def sort(alist):
    for turn in range(len(alist)-1):
        max_index = 0
        for index in range(1,len(alist)-turn):
            if alist[index] > alist[max_index]:
                max_index = index
        alist[max_index], alist[len(alist)-1-turn] = alist[len(alist)-1-turn], alist[max_index]
    return alist

print(sort(alist))

11.3 插入排序(一种特殊形式的希尔排序)

11.3.1 概念和解题思路

https://i-blog.csdnimg.cn/blog_migrate/1474fb947347967cc60519690cc9c933.png

11.3.2 分步实现代码

  1. 第一步:有序集合中只有一个元素,乱序集合中第一个元素和有序集合中唯一的一个元素比较完就行了
alist = [3,8,5,7,6]

# 将第一个元素3作为有序子集合,后面的8,5,7,6作为无序子集合
# i是有序集合中元素的个数,也是无序集合中第一个元素8在原始数组中的下标(alist[i]=8);而alist[i-1]=3是有序集合中最后一个元素在原始数组中的下标
i = 1
if alist[i] < alist[i-1]:   # 如果乱序子集中第一个元素8小于有序子集中最后一个元素3,则交换位置
    alist[i], alist[i-1] = alist[i-1], alist[i]
else: # 如果乱序子集合中第一个元素8大于等于有序子集中最后一个元素3,则什么也不做
    pass
i+=1  # i要加1,让有序子集变成2个元素,乱序集合第一个元素变为alist[2]
  1. 第二步:有序集合中有两个元素,乱序集合中第一个元素需要和有序集合中两个元素都比较一次
alist = [3,8,5,7,6]
i = 2
while i > 0:
    if alist[i] < alist[i-1]:   # 如果乱序子集中第一个元素5小于有序子集中最后一个元素8,则交换位置
        alist[i], alist[i-1] = alist[i-1], alist[i]
        i -= 1 # i回退1是因为现在有序集合中的元素已经不是一个了,而是两个,所以和有序集合中最后一个元素比较完还要和前面的元素比较
    else: # 如果乱序子集合中第一个元素5大于等于有序子集中最后一个元素8,则退出循环
        break
  1. 第三步:有序集合中有三个元素,乱序集合中第一个元素需要和有序集合中三个元素都比较一次

    i = 3

  2. 第四步:有序集合中有四个元素,乱序集合中第一个元素需要和有序集合中四个元素都比较一次

    i = 4

  3. 第五步:有序集合中有五个元素,乱序集合中第一个元素需要和有序集合中五个元素都比较一次

    i = 5

  4. 第六步:将前五步合并成最后的代码

def sort(alist):
    for i in range(1,len(alist)):
        while i > 0:
            if alist[i] < alist[i-1]:
                alist[i], alist[i-1] = alist[i-1], alist[i]
                i-=1
            else:
                break

11.4 希尔排序

11.4.1 概念和解题思路

希尔排序是插入排序的一种也叫缩小增量排序是直接插入排序算法的一种更高效的改进版本该方法的基本思想是先将整个待排元素序列分割成若干个子序列由相隔某个增量gap的元素组成分别进行直接插入排序然后依次缩减增量再进行排序待整个序列中的元素基本有序增量足够小再对全体元素进行一次直接插入排序因为直接插入排序在元素基本有序的情况下效率是最高的因此希尔排序在时间效率比直接插入排序有较大提高
gap是增量值也是拆分出来的子数组的个数

https://i-blog.csdnimg.cn/blog_migrate/ed5014152749a2fa6bdf94dc7851d133.png#pic_center

11.4.2 分步实现代码

def sort(alist):
    gap = len(alist) // 2
    #将插入排序当做增量为1的希尔排序
    for i range(1,len(alist)):
        while i > 0 :
            if alist[i] < alist[i-1]:
                alist[i],alist[i-1] = alist[i-1],alist[i]
                i -= 1
            else:
                break
def sort(alist):
    gap = len(alist) // 2
    #将增量设置成gap
    for i range(gap,len(alist)):
        while i > 0 :
            if alist[i] < alist[i-gap]:
                alist[i],alist[i-gap] = alist[i-gap],alist[i]
                i -= gap
            else:
                break
#继续缩小增量
def sort(alist):
    gap = len(alist) // 2
    while gap >= 1:
        #将增量设置成gap
        for i in range(gap,len(alist)):
            while i > 0 :
                if alist[i] < alist[i-gap]:
                    alist[i],alist[i-gap] = alist[i-gap],alist[i]
                    i -= gap
                else:
                    break
        gap //= 2
    return alist

11.5 快速排序

11.5.1 解题思路和分步实现步骤

  1. 指定一个基数(乱序中的第一个数据),将乱序中比基数小的放在基数的左侧;比基数大的放在基数的右侧, 要实现这一步需要分以下步骤实现

    1.1 . 指定low为乱序中第一个元素的下标0;指定high为乱序中最后一个元素的下标len(list)-1

alist = [6,1,2,7,9,3,4,5,10,8]
def sort(alist):
    # 基数
    mid = alist[0]
    low = 0
    high = len(alist)-1

https://i-blog.csdnimg.cn/blog_migrate/ca4a88e49fdb2ed0d3d759b7193e0d7b.png

1.2 . 比较规则是:

先偏移high
偏移high或low时当发生复制时改为偏移low或high
直到low和high重回时将mid的值放入重合的位置此时就实现了mid左边的数都比他小右边的数都比他大

先从右开始偏移high的位置,如果high位置的元素比mid6大那么high位置上的元素不用交换,并且将high向左偏移一个位置指向10的位置

https://i-blog.csdnimg.cn/blog_migrate/3f4fff2c9ce1b2d1fb14b7357cc49db4.png

然后继续用high位置上的值10和mid6比较,如果10大,那么high位置上的元素不用交换,并且将high向左偏移一个位置指向5的位置

https://i-blog.csdnimg.cn/blog_migrate/75c69d8be46ae8c3aaeb2c3df801285d.png

然后继续用high位置上的值5和mid6比较,如果5比mid6小,那么high位置上的元素复制到mid的位置上,并且停止偏移high,转而开始偏移low

https://i-blog.csdnimg.cn/blog_migrate/44762f09680b48edd37d501c8776545f.png

low位置上的5比mid6小,所以low位置上的5不用动,直接将low向右偏移一位到1

https://i-blog.csdnimg.cn/blog_migrate/4b103899089aa8de2fca8d5935777388.png

low位置上的1比mid6小,所以low位置上的1不用动,直接将low向右偏移一位到2

https://i-blog.csdnimg.cn/blog_migrate/ce3ef8bbd5f762a841970b8d77699a29.png

low位置上的2比mid6小,所以low位置上的2不用动,直接将low向右偏移一位到7

https://i-blog.csdnimg.cn/blog_migrate/c0ba61f979b93b61513174d0fda0e399.png

low位置上的7比mid6大,所以需要将low位置上的7复制到high指向的位置,并且停止偏移low,转而偏移high

https://i-blog.csdnimg.cn/blog_migrate/63799ddad26819578bbd8015b8f9de2b.png

high位置上的7比mid6大,所以7不用动,将high向左偏移到4

https://i-blog.csdnimg.cn/blog_migrate/992cf7f0e89ed659b5d31515b3aa0119.png

high位置上的4比mid6小,所以需要将4复制到low的位置,并且停止偏移high,转而偏移low

https://i-blog.csdnimg.cn/blog_migrate/e7b2597f91f8b81a8939df1bf25ab426.png

low位置上的4比mid6小,所以不用移动4,直接将low的位置向右移动到指向9

https://i-blog.csdnimg.cn/blog_migrate/1f93f9ef40e208c597ced2bef20ecd85.png

low位置上的9比mid6大,所以将9复制到high的位置,并且停止偏移low,转而偏移high

https://i-blog.csdnimg.cn/blog_migrate/8b969723da496dc6d10f1aee72b32eb2.png

high位置上的9比mid6大,所以9不动,直接将high向左偏移到指向3的位置

https://i-blog.csdnimg.cn/blog_migrate/162056b80a4b25529143342a258b04ac.png

high位置上的3比mid6小,所以将3复制到low的位置,并且停止偏移high,转而偏移low

https://i-blog.csdnimg.cn/blog_migrate/f9f6f3fb50272a49562bd5ea1ead61b0.png

low位置上的3比mid6小,所以3不用动,直接将low向右偏移到指向3,这时low和high重合

https://i-blog.csdnimg.cn/blog_migrate/ebc2851954c985e79e29e03c522cbf84.png

一旦low和high重回,将mid6放入这个位置。此时mid6的左侧元素都比6小;右侧元素都比6大

https://i-blog.csdnimg.cn/blog_migrate/47376a4127cdb165419f8bdd316a9e0f.png

1.3 这步代码实现


alist = [6,1,2,7,9,3,4,5,10,8]
def sort(alist):
    # 基数
    mid = alist[0]
    low = 0
    high = len(alist)-1

    while low < high:
        # 偏移high
        while low < high:
            if alist[high] > mid:
                # 向左偏移high
                high -= 1
            else:
                alist[low] = alist[high]
                break

        # 偏移low
        while low < high:
            if alist[low] < mid:
                low += 1
            else:
                alist[high] = alist[low]
                break
        if low == high:
            alist[low] = mid
            break
    return alist
  1. 用递归将基数左侧乱序序列和右侧乱序序列执行上面的步骤,直到之后的基数左侧只有一个元素,右侧只有一个元素为止
def sort(alist,start,end):
    low = start
    high = end
    #递归结束的条件
    if low > high:
        return
    #基准:最左侧的数值
    mid = alist[low]
    #low和high的关系只能是小于,当等于的时候就要填充mid了
    while low < high:
        while low < high:
            if alist[high] > mid:
                high -= 1
            else:
                alist[low] = alist[high]
                break
        while low < high:
            if alist[low] < mid:
                low += 1
            else:
                alist[high] = alist[low]
                break
        
        #当low和high重复的时候,将mid填充
        if low == high:
            alist[low] = mid #or alist[high] = mid  
            break
    #执行左侧序列
    sort(alist,start,high-1)
    #执行右侧序列
    sort(alist,low+1,end)
    
    return alist