您的位置:首页 > 其它

几种常见排序算法

2014-08-21 10:48 176 查看
在这里记录一下v_JULY_v专家的博客:http://blog.csdn.net/v_july_v,记录在这里,多多去学习。

这里主要是几种常见算法的Python写法,做个备忘:

#!/usr/bin/env python
#coding:utf-8

import random
from datetime import datetime

'''
插入排序
特点:stable sort、In-place sort
最优复杂度:当输入数组就是排好序的时候,复杂度为O(n),而快速排序在这种情况下会产生O(n^2)的复杂度。
最差复杂度:当输入数组为倒序时,复杂度为O(n^2)
思想:每次将一个待排序的数据按照其值的大小插入到前面已经排序好的数据中的适当位置,直到全部数据排序完成。
应用场景:适合用于“少量元素的数组”或者数组大致已经排好序。
'''
def insert_sort(A):
for i in range(1, len(A)):
key = A[i]#取出待排序的值
j = i - 1
while(j >= 0):#向前比较
if A[j] > key:
A[j + 1], A[j] = A[j], key#将key插在j位置
else:
break
j -= 1

'''
冒泡排序
特点:stable sort、In-place sort
思想:通过两两交换,像水中的泡泡一样,小的先冒出来,大的后冒出来。
最坏运行时间:O(n^2)
最佳运行时间:O(n^2)(当然,也可以进行改进使得最佳运行时间为O(n))
思想:对待排序元素的关键字从后往前进行多遍扫描,遇到相邻两个关键字次序与排序规则不符时,就将这两个元素进行交换。这样关键字较小的那个元素就像一个泡泡一样,从最后面冒到最前面来。
'''
def bubble_sort(A):
flag = True
for i in range(0, len(A)):
if(flag == False):
continue
flag = False#加flag判断减少比较次数,可将时间复杂度降低为O(n)
for j in range(len(A) - 2, i - 1, -1):#从后往前扫描、交换
if(A[j] > A[j + 1]):
tmp = A[j]
A[j] = A[j + 1]
A[j + 1] = tmp
flag = True

'''
选择排序
特性:In-place sort,unstable sort。
思想:每次找一个最小值。
最好情况时间:O(n^2)。
最坏情况时间:O(n^2)。
思想:每次遍历,选出键值最小的数据,依次放在已排序好的数列后面,直到全部记录排完为止。
'''
def select_sort(A):
for i in range(len(A) - 1):
mini = i
for j in range(i + 1, len(A)):
if(A[mini] > A[j]):
tmp = A[mini]
A[mini] = A[j]
A[j] = tmp

'''
并归排序
特点:stable sort、Out-place sort
思想:运用分治法思想解决排序问题。
最坏情况运行时间:O(nlgn)
最佳运行时间:O(nlgn)
'''
def merge_sort(A):
def marge(A, l, m, r):
L = A[l : m + 1] + [0xFFFFFFFF]
R = A[m + 1 : r + 1] + [0xFFFFFFFF]
i = j = 0
for k in range(l, r + 1):
if(L[i] <= R[j]):
A[k] = L[i]
i += 1
elif(L[i] > R[j]):
A[k] = R[j]
j += 1

def recursive_merge_sort(A, l, r):
if(l < r):
m = (l + r) / 2
recursive_merge_sort(A, l, m)
recursive_merge_sort(A, m + 1, r)
marge(A, l, m, r)

recursive_merge_sort(A, 0, len(A) - 1)

'''
快速排序
特性:unstable sort、In-place sort。
最坏运行时间:当输入数组已排序时,时间为O(n^2),当然可以通过随机化来改进(shuffle array 或者 randomized select pivot),使得期望运行时间为O(nlgn)。
最佳运行时间:O(nlgn)
思想:把待排列的数据分为两个子列,从数列中挑出一个数作为基准,遍历其他数据,把小于它的放前面,大的放在基准的后面。之后,通过递归,将各个子序列划分为更小的序列,直到把小于基准值元素的子数列和大于基准值元素的字数列排序。
'''
def quick_sort(A):
def partition(A, l, h):#拆分为两个子列,并返回基准位置
pivot = A[l]#基准
while(l < h):#这里一个循环交换一个数据
while(l < h):
if(A[h] < pivot):#从右往左找出第一个比基准小的数据,将这个数放到基准的左边,实际上是与基准交换即可
tmp = A[h]
A[h] = A[l]
A[l] = tmp
break
h -= 1

while(l < h):
if(A[l] > pivot):#从左往右找出第一个比基准大的数据,将这个数放到基准的右边,实际上是与基准交换即可
tmp = A[h]
A[h] = A[l]
A[l] = tmp
break
l += 1
return l#返回新的基准位置

def recursive_quick_sort(A, l, h):
if(l < h):
m = partition(A, l, h)
recursive_quick_sort(A, l, m - 1)
recursive_quick_sort(A, m + 1, h)

recursive_quick_sort(A, 0, len(A) - 1)

'''
堆排序
特性:unstable sort、In-place sort。
最优时间:O(nlgn)
最差时间:O(nlgn)
思想:运用了最小堆、最大堆这个数据结构,而堆还能用于构建优先队列。
'''
def heap_sort(A):
'''这里i统一为数组下标'''
def parent(i):
return i and ((i - 1) >> 1) or 0

def left(i):
return (i << 1) + 1

def right(i):
return (i << 1) + 2

'''保持堆的性质'''
def heapify(A, i, size):

l = left(i)
r = right(i)

largest = i
if l < size and A[i] < A[l]:
largest = l

if r < size and A[largest] < A[r]:
largest = r

if largest != i:
A[largest], A[i] = A[i], A[largest]
heapify(A, largest, size)

def build(A):
for i in range(len(A) / 2, 0, -1):#从下往上遍历,叶子节点没有子节点了不需要处理
heapify(A, i - 1, len(A))

build(A)
for i in range(len(A) -1, 0, -1):
A[0], A[i] = A[i], A[0]#交换最大值和最小值
heapify(A, 0, i)#除去最大值剩余的元素进行堆化,堆化后,array[0]又为最大值,重复堆化操作

'''
测试
'''
if __name__ == '__main__':
A = [91, 3, 5, 6, 7, 9, 21, 23, 23, 2111, 3, 4, 9, 12, 33, 9, 21, 115560202]
quick_sort(A)
print A
merge_sort(A)
print A
NUM = 10000
A = [random.randint(0, 10000) for i in range(NUM)]

print datetime.now()
insert_sort(A)
#     heap_sort(A)
print datetime.now()
print A


参考:

/article/7665056.html

/article/8454398.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: