算法学习__排序

排序:将元素集合按照规定的顺序排列

排序的分类:比较排序和线性时间排序。

基于比较排序依赖于比较和交换来将元素移动到正确的位置上。令人惊讶的是,并不是所有的排序算法都依赖于比较。对于那些确实依赖于比较来进行排序的算法来说,它们的运行时间往往不可能小于O(nlg(n)),即nlgn是下界。对于线性时间排序,从它的名字可以看出,它的运行时间为O(n)。但是线性时间的排序依赖于数据集合中的某些特性,并不是所有的场合都能使用它。

稳定性排序:stable sort preserves the relative order of equal elements。

堆排序、快速排序、希尔排序、直接选择排序不是稳定的排序算法,而基数排序、冒泡排序、直接插入排序、折半插入排序、归并排序是稳定的排序算法。

下面用python实现部分排序算法

(1)插入排序

插入排序虽然不是最有效的排序算法,但它简单,且不需要额外的存储空间。其最佳应用场景是对一个小的数据集合进行递增排序。

(2)快速排序

在一般的情况下,一致认为快排是最好的一种排序算法,而且不需要额外的存储空间,其最佳应用场合时应用于大型数据集

(3)归并排序

归并排序基本上与快排的性能相同,但它需要使用两倍于快排的存储空间。而具有讽刺意味的是,其最佳应用场合时在超大数据集中,因为归并排序的原理就是对原始的乱序数据不断进行对半分割。

(4)计数排序

        计数排序是一种稳定的线性时间排序算法,当知道数据集中整数的最大值的情况下,会经常用到此算法,主要用来实现基数排序。

(5)堆排序

在堆排序中,要排序的数据首先存储在一个堆中。从堆中一次取出一个结点,放置在有序数据集的尾部。当取出每个结点时,它的下一个结点就会浮现到堆顶。在实际应用中,快排往往比堆排复杂度略低,两者相差一个因子。


每种算法具体的实现:

#coding=utf-8
import unittest
import random
#############################################
# 算法学习——排序和搜索
# 作者:chuanchuan608
# 时间:2014/11/2
#############################################

    
#插入排序:在增量排序中非常高效
#每次从未排序的数据集中取出一个元素,插入已排好序的数据库中。
#该方法由于在决定将元素插入哪个位置前,需要将被插入的元素和有序
#数据集中的其他元素进行比较,这会增加额外开销,因此在处理大型数
#据集时并不高效。
def InsertSort(L):
    if len(L) <= 1:
        return L
    
    for i in range(1, len(L)):
        tmp = L[i]
        j = i - 1
        while j >= 0 and tmp < L[j]:
            L[j + 1] = L[j]
            j -= 1
        L[j + 1] = tmp
    
    return L
    
def BubleSort(L):
    if len(L) <= 1:
        return L
    for i in range(0, len(L)):
        for j in range(0, len(L) - 1 - i):
            if L[j]>L[j+1]:
                L[j], L[j+1] = L[j+1], L[j]
   
    return L 

# 快排是一种分治排序算法,同时也属于比较排序的一种,且不需额外内存空间
# 在处理大型数据集中,快排是一个比较好的选择。而选取枢纽元是快排是否高
# 效的关键(中位数),而中位数的选取依赖随机数的统计特性,因此快排也是
# 一种随机算法
def QuickSort(L):
    if len(L) <= 1:
        return L

    pivot = L[0]
    
    return QuickSort([x for x in L[1:] if x < pivot]) + [pivot] + QuickSort([x for x in L[1:] if x >= pivot])

def MergeSort(L):
    if len(L) < 2:
        return L[:]
    else:
        # divide
        middle = len(L)>>1; # attention
        # Conqure
        left = MergeSort(L[:middle])
        right = MergeSort(L[middle:])
        # Combine
        together = Merge(left, right)

    return together 

def Merge(left, right):
    # alloc space to store result
    result = []
    i, j = 0, 0
    
    while i < len(left) and j < len(right):
        # compare the first two element,which is the small one,
        # of each two sublists
        if left[i] <= right[j]:
            result.append(left[i])
            i = i + 1
        else:
            result.append(right[j])
            j = j + 1
    while (i < len(left)):
        result.append(left[i])
        i = i + 1
    while (j < len(right)):
        result.append(right[j])
        j = j + 1
        
    return result
    
    
# 计数排序是一种高效的线性排序,通过计算一个集合总元素出现的次数来确定集合如何排列的
# 该方法有一定的局限性,其中最大的局限就是它只能用于整型或者那些可以用整型来表示的数据
# 集合。速度快,稳定,复杂度为O(K+N),所以这里的K影响该算法的复杂度
def CountSort(L): 
    import copy
    k = max(L) + 1# k为最大整数+1
    length = len(L)
    res = []
    res = copy.copy(L)
    #initialize the counts
    counts = [0 for i in range(k)]
    #
    for j in range(len(L)):
        counts[L[j]] = counts[L[j]] + 1 
        
    for n in range(1, k):
        counts[n] = counts[n] + counts[n - 1]
        
    for m in range(length):
        index = length-1-m
        res[counts[L[index]]-1] = L[index]
        counts[L[index]] = counts[L[index]] - 1
        
    return res

# 堆排序 O(nlg(n)) 不稳定
def HeapSort(L):
    # 创建最大堆 
    for begin in range((len(L) - 2)>>1, -1, -1):
        MaxHeapAdjust(L, begin, len(L) - 1)
    # 堆排序
    for end in range(len(L) - 1, 0, -1):
        L[0], L[end] = L[end], L[0] # 取出根节点,更新堆
        MaxHeapAdjust(L, 0, end - 1)
        
    return L
    
def MaxHeapAdjust(L, begin, end):
    # 最大堆调整
    import copy
    retLst= []
    
    root = begin
    
    while True:
        child = 2 * root + 1
        if child > end:
            break   # 跳出 
        if child + 1 <= end and L[child] < L[child + 1]:
            child = child + 1
        if L[root] < L[child]:
            L[root], L[child] = L[child], L[root] # 交换
            root = child
        else:
            break
            
    retLst = copy.deepcopy(L)
    return retLst
#test
class test_case(unittest.TestCase):
   
    def setUp(self):
        pass
    def tearDown(self):
        pass
        
    def test_InsertSort(self): 
        print('InsertSort ...')
        testData = [random.randrange(0, 1000) for _ in range(1000)]
        self.assertEqual(InsertSort(testData), sorted(testData))

    def test_BubleSort(self):
        print('BubleSort ...')
        testData = [random.randrange(0, 1000) for _ in range(1000)]
        self.assertEqual(BubleSort(testData), sorted(testData))
        
    def test_QuickSort(self):
        print('QuickSort ...')
        testData = [random.randrange(0, 1000) for _ in range(1000)]
        self.assertEqual(QuickSort(testData), sorted(testData))  

    def test_MergeSort(self):
        print('MergeSort ...')
        testData = [random.randrange(0, 1000) for _ in range(1000)]
        self.assertEqual(MergeSort(testData), sorted(testData))   

    def test_CountSort(self):
        print('CountSort ...')
        testData = [random.randrange(0, 1000) for _ in range(1000)]
        self.assertEqual(CountSort(testData), sorted(testData))     
    
    def test_HeapSort(self):
        print('HeapSort ...')
        testData = [random.randrange(0, 1000) for _ in range(1000)]
        self.assertEqual(HeapSort(testData), sorted(testData))   
if __name__ == '__main__':
    unittest.main()





你可能感兴趣的:(算法学习__排序)