算法--排序算法

选择排序

# 选择排序
# 选择排序思路:
# - 每次从 [i,n-1] 区间中选择最小值,放到 i 位置上
# - i 取值为 [0,n-1],因为如果最后只有一个数,则无需查询,i 取值为 [0,n-2] 即可
def select_sort(nums: list[int]):
    n = len(nums)
    if n <= 1:
        return
    
    for i in range(n - 1):
        k = i # 用k表示最小值索引
        for j in range(i + 1, n):
            if nums[k] > nums[j]:
                k = j
        if k != i:
            swap(nums, i, k)

def swap(nums: list[int], i: int, j: int):
    temp = nums[i]
    nums[i] = nums[j]
    nums[j] = temp

nums = [1,3,4,2,3,4,5,67,12,23,34]
select_sort(nums)
print(nums)

冒泡排序

n 长度数组 nums

思路:

第一次:在 [0, n-1] 区间内冒泡

第二次:在 [0, n-2] 区间内冒泡

.....

最后一次:在 [0, 1] 区间内冒泡

伪代码:

  for k from n-1 to 1:

    在 [0, k] 区间内冒泡

 

冒泡思路:在 [0, k] 区间内冒泡

第一次:if nums[0] > nums[1] 则交换

第一次:if nums[1] > nums[2] 则交换

。。。

最后一次:if nums[k-1] > nums[k] 则交换

伪代码:

  for i from 0 to k-1:

    if nums[i] > nums[i+1]

      swap(nums, i, i+1) 

同时:n > 1 排序才有意义

def buddle_sort(nums: list[int]):
    n = len(nums)
    for t in range(n-1, 0, -1):
        for i in range(0, t):
            if nums[i] > nums[i + 1]:
                swap(nums, i, i + 1)

def swap(nums: list[int], i: int, j: int):
    temp = nums[i]
    nums[i] = nums[j]
    nums[j] = temp


nums = [1,3,4,2,3,4,5,67,12,23,34]
buddle_sort(nums)
print(nums)
public void bubble_sort(int[] nums) {
    int n = nums.length;
    if (n <= 1) return;

    for (int t = n - 1; t >= 1; t--) {
        for (int i = 0; i <= t - 1; i++) {
            if (nums[i] > nums[i + 1]) {
                swap(nums, i, i + 1);
            }
        }
    }
}

private void swap(int[] nums, int i, int j) {
    int t = nums[i];
    nums[i] = nums[j];
    nums[j] = t;
}

插入排序:

# 插入排序(类似扑克牌)
def insert_sort(nums: list[int]):
    n = len(nums)
    if n <= 1:
        return
    
    for k in range(1, n):
        base = nums[k]
        j = k - 1
        while j >=0 and nums[j] > base:
            nums[j + 1] = nums[j]
            j = j - 1
        nums[j + 1] = base

快速排序:

核心点在于寻找哨兵位,然后递归排序哨位位左侧区间和右侧区间



def quick_sort(nums: list[int]):
    '''快速排序'''
    quick_sort_helper(nums, 0, len(nums) - 1)

def quick_sort_helper(nums: list[int], left: int, right: int):
    '''递归子方法'''
    if right <= left:
        return
    # 哨兵位
    p = part(nums, left, right)
    # 递归排序哨兵左侧区间
    quick_sort_helper(nums, left, p - 1)
    # 递归排序哨兵右侧区间
    quick_sort_helper(nums, p + 1, right)

def part(nums: list[int], left: int, right: int) -> int:
    i = left
    j = right
    while i < j:
        # 从右边往左找第一个小于哨兵的位置
        while i < j and nums[j] >= nums[left]:
            j = j - 1
        
        # 从左边往右边找第一个大于哨兵的位置
        while i < j and nums[i] <= nums[left]:
            i = i + 1
        
        # 交换
        swap(nums, left, i)
    return i
    
def swap(nums: list[int], i: int, j: int):
    temp = nums[i]
    nums[i] = nums[j]
    nums[j] = temp


nums = [1,3,4,2,3,4,5,67,12,23,34]
quick_sort(nums)
print(nums)

Copilot 写的(写的清晰明了多了)

def quicksort(arr):
    if len(arr) <= 1:
        return arr
    pivot = arr[len(arr) // 2]
    left = [x for x in arr if x < pivot]
    middle = [x for x in arr if x == pivot]
    right = [x for x in arr if x > pivot]
    return quicksort(left) + middle + quicksort(right)

 

归并排序:

分治思想

def merge_sort(nums: list[int]):
    '''归并排序'''
    merge_sort_helper(nums, 0, len(nums) - 1)

def merge_sort_helper(nums: list[int], left: int, right: int):
    '''递归子方法'''
    if right <= left:
        return
    # 区分点
    mid = (left + right) // 2
    # 先分
    merge_sort_helper(nums, left, mid)
    merge_sort_helper(nums, mid + 1, right)
    # 后治
    merge(nums, left, mid, right)
    
def merge(nums: list[int], left: int, mid: int, right: int):
    '''合并'''
    # 临时数组
    temp: list[int] = [0] * (right - left + 1)
    i = left
    j = mid + 1
    p = 0
    while i <= mid or j <= right:
        if j > right or (i <= mid and nums[i] <= nums[j]):
            temp[p] = nums[i]
            i = i + 1
        else:
            temp[p] = nums[j]
            j = j + 1
        p = p + 1
    # 拷贝数据
    for t in range(left, right + 1):
        nums[t] = temp[t - left]

nums = [1,3,4,2,3,4,5,67,12,23,34]
merge_sort(nums)
print(nums)

 堆排序

# 使用数组 array 来表示堆(完全二叉树)的时候
# (*)i 的父节点为 (i-1)/2
# (*)i 的子节点为 i*2+1 和 i*2+2
# 堆排序流程:
# 1、建堆
# 2、将堆顶放到堆数组尾部
# 3、堆长度-1
# 4、对堆顶进行从上到下堆化操作
# 5、重复2知道堆长度为1
def heap_sort(nums: list[int]):
    '''建堆(大顶堆)'''
    n = len(nums)
    if n <= 1:
        return
    
    # 原地堆化
    for i in range(1, n):
        sift_max_up(nums, i)
    
    print(f"建堆结果 = {nums}")
    
    # 堆顶放到末尾,依次排序
    for i in range(len(nums) - 1, 0, -1):
        swap(nums, 0, i)
        sift_max_down(nums, i - 1)
        
    
def sift_max_up(nums: list[int], i: int):
    '''从底向上堆化'''
    while i > 0:
        parent = (i - 1) // 2
        if nums[i] > nums[parent]:
            swap(nums, i, parent)
        i = parent

def sift_max_down(nums: list[int], end: int):
    '''从顶向下堆化'''
    i = 0
    while True:
        p = i
        left = 2 * i + 1
        right = 2 * i + 2
        if left > end and right > end:
            break
        
        if left <= end:
            if nums[p] < nums[left]:
                p = left
        
        if right <= end:
            if nums[p] < nums[right]:
                p = right

        if p == i:
            break
        
        swap(nums, i, p)
        i = p

def swap(nums: list[int], i: int, j: int):
    temp = nums[i]
    nums[i] = nums[j]
    nums[j] = temp
    
nums = [1,3,4,2,3,4,5,67,12,23,34]
heap_sort(nums)
print(nums)

计数排序:

# 算法步骤:
# (1)找出最大值Max
# (2)新建Max+1长度数组temp,统计每个数a出现的次数c,temp[a] = c
# (3)将统计结果回填到array 
def count_sort(nums: list[int]):
    '''计数排序'''
    n = len(nums)
    if n <= 1:
        return
    
    max = nums[0]
    for i in range(0, n):
        if max < nums[i]:
            max = nums[i]
    
    temp = [0] * (max + 1)
    for i in range(0, n):
        temp[nums[i]] = temp[nums[i]] + 1
    
    p = 0
    for i in range(0, max + 1):
        while temp[i] > 0:
            nums[p] = i
            p = p + 1
            temp[i] = temp[i] - 1

nums = [1,3,4,2,3,4,5,67,12,23,34]
count_sort(nums)
print(nums)

基数排序:

def radix_sort(nums: list[int]):
    '''基数排序'''
    n = len(nums)
    if n <= 1:
        return
    
    max_num = max(nums)
    
    exp = 1
    while exp <= max_num:
        radix_sort_digital(nums, exp)
        exp = exp * 10

def radix_sort_digital(nums: list[int], exp):
    '''按位数字排序'''
    temp = [0] * 10
    for i in range(0, len(nums)):
        num = nums[i]
        d = get_digital(num, exp)
        temp[d] = temp[d] + 1
    
    # 计算前缀和,前缀和即为元素num的最后一个下标位置
    for i in range(1, 10):
            temp[i] = temp[i] + temp[i - 1]
    
    res = [0] * len(nums)
    for num in nums:
        d = get_digital(num, exp)
        p = temp[d] - 1
        res[p] = num
        temp[d] = temp[d] - 1
    
    for i in range(0, len(nums)):
        nums[i] = res[i]
    
def get_digital(num: int, exp): 
    return (num // exp) % 10

nums = [1,3,4,1241241431,2241241431,2,3,4,5,67,12,23,34]
radix_sort(nums)
print(nums)

 

posted @ 2024-12-10 22:15  lenbkan  阅读(3)  评论(0编辑  收藏  举报