快速排序单链表版本
基本过程:
- 用两个指针i, j分别指向第一和第二个节点
- 比较j所指向的元素和链表第一个节点的值(作为基轴)的大小,
如果j指向的元素较小,则j ++
否则(1)i ++;(2)swap(i,j);j ++ - 重复步骤2,知道超出范围。
- 将基准元素和i指向的位置,交换,则I所在的位置已经排好了
- 递归左边一半sort(left, i)
- 递归右边一半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()