常见排序算法python实现

1. 冒泡排序

冒泡排序法的复杂度是O(n^2)

# buble sort
def buble_sort(inList):
    for i in range(len(inList)):
        for j in range(len(inList)-i-1):
            if inList[j] <= inList[j+1]:
                continue
            else:
                inList[j], inList[j+1] = inList[j+1], inList[j]
    return inList

2插入排序

插入排序,取数组里每一个元素,插入一个新的列表里,插入的时候,保证新的列表按照顺序排列,把最后一个元素插入完成之后,也完成了整个数组的排序。以下为实现方式。

#insertion sort
def insertion_sort(list1):
    temp = []
    for i in range(len(list1)):
    	# 每一个循环,往temp中放入一个数据
        temp.append(list1[i])
        j = len(temp) - 1
        while True and j>0:
        	# 如果数组中有数据,则把数据放入放在第一个大于他的数字前面,从而保证排序
            if temp[j] < temp[j-1]:
                temp[j], temp[j-1] = temp[j-1], temp[j]
            j -= 1
    return temp

实现过程中,temp完全可以不存在。程序编写如下。

 def insertion_sort(list1):
    for i in range(2, len(list1)):
    	# 每一个循环,往temp中放入一个数据\
        j = i
        while True and j>0:
        	# 如果数组中有数据,则把数据放入放在第一个大于他的数字前面,从而保证排序
            if list1[j] < list1[j-1]:
                list1[j], list1[j-1] = list1[j-1], list1[j]
            j -= 1

3归并排序

归并排序是采用分而治之的原则,先将要排序的数组分成两部分,再将剩余部分再分,直至每个数组只剩下一个或者两个元素,进行排序。之后,再进行归并。
算法核心部分是归并的过程,分别从两个数组中取元素,按照顺序排列,当其中一个取尽时,另一个数组剩下的部分就追加到这个元素后面,从而实现排序的目的。

# merge ort
def merge(list1, list2):
    temp = []
    i = j = 0
    while True:
        if i== len(list1):
            temp.extend(list2[j:])
            break
        if j== len(list2):
            temp.extend(list1[i:])
            break

        if list1[i] <= list2[j]:
            temp.append(list1[i])
            i += 1
        else:
            temp.append(list2[j])
            j += 1
    return temp

def merge_sort(list1):
    length = len(list1)
    if length == 1:
        return list1
    elif length == 0:
        return []
    splitIndex = int(length/2)
    left_arr = list1[:splitIndex]
    right_arr = list1[splitIndex:]
    return merge(merge_sort(left_arr), merge_sort(right_arr))

4堆排序

堆排序主要分三个过程

  1. 构建最大堆或者最小堆
    最大堆满足的性质:A[parent[i]] >= A[i]
    最小堆满足的性质:A[parent[i]] <= A[i]
  2. 交换堆顶和本次调整最后一个数据。
  3. 最大节点值减掉1,重复前两步
import random
def reAdjustHeap(dataIn, maxNodeIndex):
    nodeIndex = (maxNodeIndex-1)//2
    while nodeIndex>=0:
        # adjust node
        leftIndex =  nodeIndex*2 + 1
        rightIndex = nodeIndex*2 + 2
        if rightIndex <= maxNodeIndex:
            if dataIn[nodeIndex]<dataIn[rightIndex]:
                dataIn[nodeIndex], dataIn[rightIndex] = dataIn[rightIndex], dataIn[nodeIndex]
        if dataIn[nodeIndex]<dataIn[leftIndex]:
                dataIn[nodeIndex], dataIn[leftIndex] = dataIn[leftIndex], dataIn[nodeIndex]
        nodeIndex -= 1

def heapSort(Arr):
    maxNodeIndex = len(Arr)-1
    while maxNodeIndex>1:
        reAdjustHeap(Arr, maxNodeIndex)
        print("dataIn[0]={} dataIn[maxNodeIndex]={} maxNodeIndex".format(Arr[0], Arr[maxNodeIndex],maxNodeIndex))
        # swap head with tail
        Arr[0], Arr[maxNodeIndex] = Arr[maxNodeIndex], Arr[0] 
        maxNodeIndex -= 1

if __name__ == "__main__":
    length = 1000
    A = [random.randint(0,length) for i in range(length)]
    heapSort(A)
    print(A)

5最大(小)优先队列

堆排序的一个典型应用就是最大(小)优先队列。
最大有限序列支持的方法有

  1. Insert:将一个新元素增加到新新的集合中
  2. max :返回最大键字的元素
  3. extractMax:返回并去掉最大键字元素。
  4. increaseKey:将一个关键字的值增加到另一个值
class PriorityQueue():
    def __init__(self, arrData=None):
    # 初始化,并排成最大堆
        self.data = []
        if arrData is not None:
            self.data = arrData
        self.reAdjustHeap(self.data, len(self.data)-1)
	
    def heapSort(self):
    	# 实现堆排序,但结果保存在副本,不对原数据造成影响
        Arr = self.data[:]
        maxNodeIndex = len(Arr)-1
        while maxNodeIndex>1:
            self.reAdjustHeap(Arr, maxNodeIndex)
            # swap head with tail
            Arr[0], Arr[maxNodeIndex] = Arr[maxNodeIndex], Arr[0] 
            maxNodeIndex -= 1  
        return Arr 

    @staticmethod
    def reAdjustHeap(dataIn, maxNodeIndex):
    	# 静态方法,完成最大堆调整
        nodeIndex = (maxNodeIndex-1)//2
        while nodeIndex>=0:
            # adjust node
            leftIndex =  nodeIndex*2 + 1
            rightIndex = nodeIndex*2 + 2
            if rightIndex <= maxNodeIndex:
                if dataIn[nodeIndex]<dataIn[rightIndex]:
                    dataIn[nodeIndex], dataIn[rightIndex] = dataIn[rightIndex], dataIn[nodeIndex]
            if dataIn[nodeIndex]<dataIn[leftIndex]:
                    dataIn[nodeIndex], dataIn[leftIndex] = dataIn[leftIndex], dataIn[nodeIndex]
            nodeIndex -= 1

	# 插入操作
    def insert(self, data):
        self.data = list(set(self.data) | {data})
        self.reAdjustHeap(self.data, len(self.data)-1)
        
	# 返回堆顶
    def maxData(self):
        return self.data[0]
        
	# 返回并去除堆顶
    def extractMaxData(self):
        maxNodeIndex = len(self.data)-1
        self.data[0], self.data[maxNodeIndex] = self.data[maxNodeIndex], self.data[0] 
        maxData = self.data[-1]
        del self.data[-1]
        return maxData
    
    # 更改优先级
    def updateKey(self, i, data):
        self.data[i] = data
        if data< self.data[parentNode]:
            return self.data
        reAdjustHeap(dataIn, maxNodeIndex)
        return self.data
        
if __name__ == "__main__":
    obj = PriorityQueue([3,12,5])
    print(obj.data)

快速排序

快速排序的思想是分治,将一个完整数组分解成一个个更小的数组进行排序。
其核心部分是对数组进行分割的过程,即取一个分割数组的元素,然后将数组分成小于等于这个元素和大于这个元素的两部分。
最终实现原址排序的效果

def quickSort(A, p, r):
    if p >= r:
        return
    # 数据分割
    q = partition(A, p, r)
    quickSort(A, p, q-1)
    quickSort(A, q, r)

def partition(A, p, r):
    print("p={} r={}".format(p,r))
    splitElement = A[r]
    i = p
    for j in range(p+1, r):
        if A[j] <= splitElement:
            i += 1
            A[i], A[j] = A[j], A[i]

    A[i+1], A[r] = A[r], A[i+1]
    return i+1

if __name__ == "__main__":
    data = [1, 4, 7, 9, 12, 10, 8,4, 8] 
    quickSort(data, 0, len(data)-1)
    print(data)           

以上算法中,分割元素都是采用的是取最后一个元素作为分割元素,这样有可能会影响算法效率,一种改进措施是,采用随机算法选取分割元素(主元素)。将partition函数按照如下方式进行改写。

def quickSort(A, p, r):
    if p >= r:
        return
    q = partition(A, p, r)
    quickSort(A, p, q-1)
    quickSort(A, q, r)

def partition(A, p, r):
    import random
    print("p={} r={}".format(p,r))
    # 随机选取主元素
    splitElement = A[random.randint(p,r)]
    i = p
    for j in range(p+1, r):
        if A[j] <= splitElement:
            i += 1
            A[i], A[j] = A[j], A[i]

    A[i+1], A[r] = A[r], A[i+1]
    return i+1

if __name__ == "__main__":
    data = [1, 4, 7, 9, 12, 10, 8,4, 8] 
    quickSort(data, 0, len(data)-1)
    print(data)           

计数排序

计数排序的要求是,输入数据位非负整数序列。
核心思想是,利用数组索引的顺序特性,将数据元素转化为数组的索引,这样实现自动排序的目的。
计数排序再实现速度的同时,也牺牲了空间。如代码中,C数组的使用,浪费的大量空间。

def countSort(A):
    # 初始化C用于计数
    maxIndex = max(A)
    minIndex = min(A)
    C = []
    [C.append(0) for _ in range(maxIndex-minIndex+1)] 

    # 统计每一个元素的,其实就默认实现了数组的排序
    for i in range(len(A)):
        C[A[i]-minIndex] += 1
    
    # 取出结果放到B中
    B = []
    for j in range(len(C)):
        count = C[j]
        # print("count={}".format(count))
        while count > 0:
            B.append(j+minIndex)
            count -= 1

    return B

if __name__ == "__main__":
    A = [10, 3, 5, 7, 9, 4]
    print(countSort(A))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值