排序算法

冒泡排序(bubble sort)

冒泡排序是指每次比较相邻的两个数,如果前一个数大于后一个数,则两个数进行交换,每遍历一次,即可得到一个最大数,最坏情况需要遍历n-1次。
Python代码实现如下:

def Bubble_Sort(arr):
    exchange = False
    length = len(arr)
    num = 0
    while num < length and not exchange:
        exchange = True
        for j in range(length-num-1):
            if arr[j] > arr[j+1]:
                arr[j], arr[j+1] = arr[j+1], arr[j]
                exchange = False
        num += 1
    return arr

选择排序(selection sort)

选择排序 每次遍历只进行一次数据交换,第一次遍历找出最大或最小的数,第二次遍历找剩余数中的最大或最小数,总共需要进行n-1次遍历。
Python代码实现如下:

def Selection_Sort1(arr, sortmode='up'):
    length = len(arr)
    for i in range(length-1):
        index = 0
        for j in range(length-i-1):
            if sortmode == 'up':
                if arr[index] < arr[j+1]:
                    index = j + 1
            else:
                if arr[index] > arr[j+1]:
                    index = j + 1
        arr[index], arr[j+1] = arr[j+1], arr[index]
        print(arr)
    return arr

插入排序 (insertionSort)

插入排序是将数插入到一个有序数列中,最终得到一个有序的数列。
Python代码实现如下:

def insertionSort(alist):
   for index in range(1,len(alist)):
     currentvalue = alist[index]
     position = index
     while position > 0 and alist[position-1] > currentvalue:
         alist[position] = alist[position-1]
         position = position-1
     alist[position] = currentvalue
   return alist

希尔排序(shell sort)

希尔排序是将原数列分解为多个子数列,然后对每个子数列使用插入排序进行排序。在希尔排序中,分解为多个子数列并不是对原数列进行连续拆分,而是通过增量的形式来对原数列进行拆分,得到多个子数列。例如数组[1,2,3,4,5,6,7,8,9],使用增量3来拆分原数组,得到三个子数组[1, 4, 7]、 [2, 5, 8]、[3, 6, 9]
Python代码实现如下:

def Shell_Sort(arr):
    subcount = len(arr) // 2
    while subcount > 0:
        for start in range(subcount):
            #insert sort
            for i in range(start+subcount, len(arr), subcount):
                current = arr[i]
                pos = i
                while pos > 0 and arr[pos-subcount] > current:
                    arr[pos] = arr[pos-subcount]
                    pos -= subcount
                arr[pos] = current
        subcount = subcount // 2
    
    return arr

归并排序(merge sort)

归并排序是基于分治法的思想来设计的。归并排序是一种递归算法,它不断将数列拆分为一半,直到数列中只有一个 元素时,进行排序。此外,还需要一个合并的操作,将两个有序的数列重新合并为一个有序的数列。
Python代码实现如下:

def mergeSort(alist):
    print("Splitting ",alist)
    if len(alist)>1:
        mid = len(alist)//2
        lefthalf = alist[:mid]
        righthalf = alist[mid:]
        
        mergeSort(lefthalf)
        mergeSort(righthalf)
        
        #进行归并排序
        i=0
        j=0
        k=0
        while i < len(lefthalf) and j < len(righthalf):
            if lefthalf[i] <= righthalf[j]:
                alist[k]=lefthalf[i]
                i=i+1
            else:
                alist[k]=righthalf[j]
                j=j+1
            k=k+1

        while i < len(lefthalf):
            alist[k]=lefthalf[i]
            i=i+1
            k=k+1

        while j < len(righthalf):
            alist[k]=righthalf[j]
            j=j+1
            k=k+1
    print("Merging ",alist)

快速排序(quick sort)

快速排序也是基于分治法来设计的,相对于归并排序,快速排序不需要额外的空间和合并操作。首先,快速排序会先选择一个值,作为分割值( pivot value)。一般可以选择数列的第一项或者使用中值三来选择,中值三是在数列中的第一项、中间项和最后一项中选择中间值作为分割值。根据分割值,将原数列分割为小于分割值和大于分割值得两部分。
分割方法是通过左标记(leftmark)和右标记(rightmark)来实现的。例如数组[10, 5,12,8,45,19,8,6,78],选取第一个元素10作为分割值其分割过程如下:
首先,leftmark指向5,rightmark指向最后一个元素78,如果leftmark指向的数小于分割值10,则leftmark指向下一个元素,否则leftmark停止移动;
然后,判断rightmark指向的元素是否大于分割值10,如果大于,则移动rightmark到下一个元素,否则停止移动;
最后,交换leftmark指向的元素和rightmark指向的元素;
如此循环,直到rightmark小于leftmark时,rightmark指向的数与分割值10交换。
数组[10, 5,12,8,45,19,8,6,78]的
第一次交换是12和6交换
第二次交换是45和8
第三次交换是8和10
最终交换完成后的数列如下
[8, 5,6,8, 10, 19,45,12,78]
接下来对数组[8, 5,6,8,]和数组[19,45,12,78]分别进行分割
当数组的长度等于1时,它已经排好序,不需要进行递归分割,如果大于1,则继续递归分割。
Python代码实现如下:

def quickSort(alist):
   quickSortHelper(alist,0,len(alist)-1)

#递归求解 
def quickSortHelper(alist,first,last):
   if first<last:
       splitpoint = partition(alist,first,last)
       quickSortHelper(alist,first,splitpoint-1)
       quickSortHelper(alist,splitpoint+1,last)

#进行分割操作,返回分割位置    
def partition(alist,first,last):
   pivotvalue = alist[first]
   leftmark = first+1
   rightmark = last
   done = False
   while not done:
       while leftmark <= rightmark and alist[leftmark] <= pivotvalue:
           leftmark = leftmark + 1
       while alist[rightmark] >= pivotvalue and rightmark >= leftmark:
           rightmark = rightmark -1
       if rightmark < leftmark:
           done = True
       else:
           temp = alist[leftmark]
           alist[leftmark] = alist[rightmark]
           alist[rightmark] = temp
   temp = alist[first]
   alist[first] = alist[rightmark]
   alist[rightmark] = temp
   return rightmark

堆排序(heap sort)

堆排序是基于二叉堆来设计的,下面先介绍二叉堆
二叉堆可以看成一棵完全二叉树,其节点i(从1开始)的父节点是i/2向下取整,在Python中可以用i//2来表示;节点i的左孩子节点是2i;节点i的右孩子节点是2i+1。此外,相对于二叉树,二叉堆还需要满足堆的性质,即所以父节点的值都要大于等于或小于等于孩子节点的值。如果是大于等于,就称为最大堆,如果是小于等于,就称为最小堆
堆排序思想:首先,将需要进行排序的数列alist=[1…n]构造成一个最大堆或最小堆,此时根节点存放的就是最大值或最小值,然后将根节点和最末尾的节点进行交换,就可以将最大值或最小值移动到最末尾的位置。接着对数列alist=[1…n-1]从新构建为最大堆或最小堆,继续交换根节点和堆的最末尾节点,如此循环,直到堆只有两个节点位置。此时,数组alist=[1…n]已经排好序(最大堆对应升序,最小堆对应降序)。
最大堆的排序算法Python实现如下:
代码来源

def heapify(arr, n, i): 
    largest = i  
    l = 2 * i + 1     # left = 2*i + 1  i可以循环到0 
    r = 2 * i + 2     # right = 2*i + 2 
  
    if l < n and arr[i] < arr[l]: 
        largest = l 
  
    if r < n and arr[largest] < arr[r]: 
        largest = r 
  
    if largest != i: 
        arr[i],arr[largest] = arr[largest],arr[i]  # 交换
  
        heapify(arr, n, largest) 
  
def heapSort(arr): 
    n = len(arr) 
  
    # Build a maxheap. 
    for i in range(n, -1, -1): 
        heapify(arr, n, i) 
  
    # 一个个交换元素
    for i in range(n-1, 0, -1): 
        arr[i], arr[0] = arr[0], arr[i]   # 交换
        heapify(arr, i, 0) 
  
arr = [ 12, 11, 13, 5, 6, 7] 
heapSort(arr) 
print ("排序前:", arr) 
heapSort(arr) 
print ("排序后: ", arr) 

上面提及的算法都可以认为是基于比较来设计的,一般称为比较排序,此外,还有不基于比较来进行排序的算法,例如计数排序、基数排序和桶排序,这种算法一般也称为线性时间排序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值