快速排序的单链表版本

快速排序单链表版本

基本过程:

  1. 用两个指针i, j分别指向第一和第二个节点
  2. 比较j所指向的元素和链表第一个节点的值(作为基轴)的大小,
    如果j指向的元素较小,则j ++
    否则(1)i ++;(2)swap(i,j);j ++
  3. 重复步骤2,知道超出范围。
  4. 将基准元素和i指向的位置,交换,则I所在的位置已经排好了
  5. 递归左边一半sort(left, i)
  6. 递归右边一半sort(i + 1, end)

可以看到,基本思想是,i右边的元素,都是大于基轴的,j往后扫描,一旦发现小于基轴的元素,则和i的下一个元素交换,将较小的元素换到左边。一轮结束后,i指向的元素值小于基轴的,所以和基轴交换。然后递归完成左右半部分。
代码如下:

#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
class Node(object):
    def __init__(self):
        self.value = None
        self.next = None
        
def swapNode(x, y):
    if x == y:
        return
    tmp = x.value
    x.value = y.value
    y.value = tmp
    
def swapArray(nums, x, y):
    if x == y:
        return
    tmp = nums[x]
    nums[x] = nums[y]
    nums[y] = tmp
    
def quick_sort(head, end):
    if head is None or head == end:
        return

    left = head
    right = head.next
    while right != end:
        if right.value < head.value:
            left = left.next
            swapNode(left, right)
        right = right.next
    # 没有数据被覆盖,只是现在,left所在位置,是pivot应该在的位置而已
    swapNode(head, left)
    quick_sort(head, left)
    quick_sort(left.next, end)

def quick_sort_array(nums, start, end):
    if start < end:
        mid = do_partition(nums, start, end)
        quick_sort_array(nums, start, mid -1)
        quick_sort_array(nums, mid + 1, end)

def do_partition(nums, start, end):
    if start >= end:
        return
    low = start
    high = end
    pivot = nums[start]
    while low < high:
        while low < high and nums[high] >= pivot:
            high -= 1
        nums[low] = nums[high]
        while low < high and nums[low] <= pivot:
            low += 1
        nums[high] = nums[low]
    nums[high] = pivot
    return high

def printLinkList(head):
    p = head.next
    while p is not None:
        print(p.value, "->", end="")
        p = p.next
    print()

def printArray(nums):
    for x in nums:
        print(str(x) , "->", end="")
    print()

def special_quick_sort(nums, start, end):
    """
       快排的本质在于选取pivot之后,交换小于pivot和大于pivot位置的数据。
       具体怎么搜索小于pivot和大于pivot的数据,有不同的方法
       (1) 从右边向左边搜索小于pivot的,从左边向右搜索大于pivot的
       (2) 不搜索大于pivot的,只从左向右搜索小于pivot的(right指针),搜索跳过的,必然是大于pivot的,可以和小于pivot的(left指针)交换(本例子做法)
       (3) 不搜素小于pivot的,只从右向左索索大于pivot的(left指针),搜索跳过的,必然是小于pivot的,可以和大于pivot的(right指针)交换
    """
    if start >= end:
        return
    left = start
    right = start + 1
    head = start
    while right <= end:
        if nums[right] < nums[head]:
            left += 1
            swapArray(nums, left, right)
        right += 1
    swapArray(nums, head, left)
    # left是在正确位置的,在迭代中是取不到的位置
    special_quick_sort(nums, start, left - 1)
    special_quick_sort(nums, left + 1, end)

def main():
    nums = [3, 7, 2, 1, 6, 0, 5, 10, 4]
    # nums = [3,2,1]
    head = Node()
    p = head
    for x in nums:
        s = Node()
        s.value = x

    p.next = s
    p = p.next
    # printLinkList(head)
    #
    # quick_sort(head.next, None)
    # printLinkList(head)

    # printArray(nums)
    # quick_sort_array(nums, 0, len(nums) - 1)
    # printArray(nums)
    printArray(nums)
    special_quick_sort(nums, 0, len(nums) - 1)
    printArray(nums)


if __name__ == "__main__":
    main()
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在C语言中,实现快速排序(QuickSort)算法通常用于数组或动态数组(如数组或动态分配的内存块),因为它们支持随机访问。然而,对于单链表这种顺序存储结构,由于不支持直接索引,快速排序的传统方法并不适用,因为快速排序依赖于元素的原地交换。对于链表,更合适的是使用迭代或递归的方式来重新排列节点,但这已经不再是标准的快速排序,而是类似于“分治”的思想,但操作方式有所不同。 一种常见的链表排序算法是归并排序,因为它适合链表的结构,不需要频繁的元素交换。如果要用类似快速排序的思想对链表进行排序,通常会采用“分而治之”的策略,先分割链表,然后递归地处理子链表,最后合并结果。但这种实现会涉及到递归和链表的操作,比较复杂。 如果你想了解如何在链表上实现类似分治的排序,可以考虑以下步骤: 1. **选择基准**:在链表中选择一个节点作为基准,通常是头节点或者随机节点。 2. **分割链表**:将链表分为两部分,一部分包含所有小于基准的节点,另一部分包含所有大于等于基准的节点。 3. **递归排序**:对这两部分链表分别进行递归排序。 4. **合并链表**:将两个已排序的链表合并成一个有序链表。 这里需要注意的是,没有原地交换操作,链表的合并可能会涉及到链表节点的插入和删除操作。 如果你对具体的代码实现感兴趣,我可以提供一个简化版的伪代码,但完整的C语言代码实现会涉及较多细节,包括链表节点的结构定义和递归调用。如果你想要详细的代码示例,请告诉我,我会尽力为你提供帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值