##时间复杂度O(NlogN)
目录
##时间复杂度O(NlogN)
##快速排序
##原理
##图例
##代码实现
##堆排序
##原理
##图例
##代码实现
##快速排序
##原理
快速排序的核心操作是“哨兵划分”,其目标是:选择数组中的某个元素作为“基准数”,将所有小于基准数的元素移到其左侧,而大于基准数的元素移到其右侧。
1.选取数组最左端作为基准数,初始化两个指针 i 和 j 分别指向数组的两端
2.设置一个循环,在每轮使用中 i(j)分别寻找第一个比基准数大(小)的元素,然后交换这个元素
3.循环执行步骤2,直到 i 和 j 相遇时停止,最后将基准值交换至两个子数组的分界线
##图例
##代码实现
#python代码示例 def partition(a, left, right) :"""哨兵划分-以a[left]为基准数"""i , j = left , rightwhile i < j :while i < j and a[j] >= a[left] :j -= 1while i < j and a[i] <= a[left] :i += 1a[i] , a[j] = a[j] , a[i]a[i] , a[left] = a[left] , a[i]return i def quick_sort(a, left, right) :if left >= right :return pivot = partition(a, left, right)quick_sort(a, left, pivot - 1 )quick_sort(a, pivot + 1 , right)
//c++代码示例 void swap(vector<int> &nums, int i , int j) {int tmp = nums[i] ;nums[i] = nums[j] ;nums[j] = tmp ; }int partition(vector<int> &nums, int left , int right) {int i = left ;int j = right ;while ( i < j ){while (i < j && nums[j] >= nums[left]){j-- ;}while (i < j && nums[i] <= nums[left]){i++ ;}swap(nums, i, j) ;}swap(nums, i , left) ;return i ; }void quickSort(vector<int> &a, int left, int right) {if (left >= right){return ;}int pivot = partition(a, left, right) ;quickSort(a, left ,pivot - 1) ;quickSort(a, pivot + 1 , right) ; }
#python代码示例 #快速排序 def QuickSortPivot(a, start, end) :pivot = startj = start + 1for i in range(start + 1 , end + 1) :if a[i] <= a[pivot] :a[i],a[j] = a[j],a[i]j += 1a[pivot],a[j-1] = a[j-1],a[pivot]pivot = j - 1print(a[pivot],a[start:pivot],a[pivot+1:end+1])return pivotdef QuickSortt(a, start, end) :if start >= end :returnpivot = QuickSortPivot(a,start,end)QuickSortt(a,start,pivot - 1)QuickSortt(a,pivot + 1,end)a = [8,5,12,6,4,3,7,9,2,1,10,11] QuickSortt(a,0,len(a)-1)print()#随机快速排序-避免最坏情况的发生 import random def RandomQuickSortPivot(a, start, end) :randomIdx = random.randint(start,end)a[randomIdx],a[start] = a[start],a[randomIdx]pivot = startj = start + 1for i in range(start+1,end+1) :if a[i] <= a[pivot] :a[i],a[j] = a[j],a[i]j += 1a[pivot],a[j-1] = a[j-1],a[pivot]pivot = j - 1print(a[pivot],a[start:pivot],a[pivot+1:end+1])return pivotdef RandomQucikSort(a, start, end) :if start >= end :returnpivot = RandomQuickSortPivot(a, start, end)RandomQucikSort(a,start,pivot-1)RandomQucikSort(a,pivot+1,end) a = [1,2,3,4,5,6,7,8,9,10,11,12] RandomQucikSort(a,0,11)
##堆排序
##原理
基于堆(完全二叉树)数据结构实现的一种高效的算法
构造堆
1.完全二叉树,从根节点开始,按照层序遍历,一定可以唯一的映射到顺序表中
2.idx = x 当前根节点的索引,idxLeft = idx * 2,idxRight = idx * 2 + 1
随机顺序表构造成为一个大顶堆(小顶堆)
1.从顺序表的最后一个元素开始自底向上的构造堆
2.对于某个元素取它左右子树中的大(小)者,如果比该元素大(小)则与该元素进行交换,直到叶子节点为止(下沉操作)
3.因为每个堆的子树都是满足堆的性质,当枚举完根节点后,这个大(小)顶堆就构造完成了
怎么实现堆排序呢
1.因为构造堆操作完成后,整个顺序表并不是一个排好序的数组
2.已知条件,堆数组的第一个元素,总是最大或者最小的,我们只需要第一个元素与最后一个元素进行交换,然后去掉被交换掉的对顶元素,重新构造成一个大(小)顶堆
3.重复操作2,直至剩余一个元素
##图例
##代码实现
#python代码示例 #堆排序-借助(堆)完全二叉树的性质来完成 #大顶堆的下沉操作 def maxHeapify(heap, start, end) :#start为堆的根节点标号,表示start - end 区间构成一个合法的堆son = start * 2 #左子树while son <= end : #左子树存在#判断右子树if son + 1 <= end and heap[son+1] > heap[son] :son += 1if heap[son] > heap[start] :heap[start] , heap[son] = heap[son] , heap[start]start , son = son , son * 2 #继续往下找直至叶子节点else :breakdef HeapSort(a) :heap = [None] + a #下标从1开始,加上一个占位符root = 1 #根节点节点编号l = len(heap) #获取对元素个数for i in range(l-1,root-1,-1) : #自底向上构造堆maxHeapify(heap,i,l-1)for i in range(l-1,root,-1) : #使第一个元素与最后一个元素发生交换heap[i],heap[root] = heap[root] , heap[i]maxHeapify(heap,root,i-1)return heap[root:] a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14] print(HeapSort(a))
#python代码示例 def sift_down(a, n , i) :"""堆的长度为n,从节点i开始,从顶至底堆化"""while True :#考虑到数组下标从0开始l = 2 * i + 1r = 2 * i + 2ma = iif l < n and a[l] > a[ma] :ma = lif r < n and a[r] > a[ma] :ma = rif ma == i :breaka[i],a[ma] = a[ma],a[i]i = madef heap_sort(a) :"""堆排序""""""构建堆,堆化除了叶子节点之外得到其他所有节点"""for i in range(len(a) // 2 - 1 , -1, -1) :sift_down(a,len(a) , i)#交换最大元素-保持堆的合法性for i in range(len(a)-1,0,-1):a[0],a[i] = a[i],a[0]sift_down(a,i,0)return a a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14] print(heap_sort(a))
//c++代码示例 void swap(a,int i ,int j) {int tmp = a[i] ;a[i] = a[j] ;a[j] = tmp ; }void siftDown(vector<int> &a, int n , int i) {while (true){int l = i * 2 + 1 ;int r = i * 2 + 2 ;int ma = i ;if (l < n && a[l] > a[ma]){ma = l ; }if (r < n && a[r] > a[ma]){ma = r ;}if (ma == i){break ;}swap(a[i],a[ma]) ;i = ma ;} }void heapSor(vector<int> &a) {for (int i = a.size()/2-1 ; i >=0 ; --i){siftDown(a,a.size(),i) ;}for (int i = a.size()-1; i > 0 ; --i){swap(a[0],a[i]) ;siftDown(a,i,0) ;} }