1 arr = [1,23,12,9,8,8,9,1,1,8,] 2 def quickSortCore(arr,start,end): 3 if start < end: 4 index = partition(arr,start,end) 5 quickSortCore(arr,start,index-1) 6 quickSortCore(arr,index+1,end) 7 8 def partition(arr,start,end): 9 key = arr[start] 10 while(start < end): 11 while(start < end and key <= arr[end]): 12 end -= 1 13 if(start < end): 14 arr[start],arr[end] = arr[end],arr[start] 15 while(start < end and key >= arr[start]): 16 start += 1 17 if(start<end): 18 arr[start],arr[end] = arr[end],arr[start] 19 return start 20 quickSortCore(arr,0,len(arr)-1) 21 print(arr)
1 package com.sort; 2 3 public class QuickSortDemo { 4 public static void main(String[] args) { 5 int []arr = {8,9,8,8,9,1,1}; 6 QuickSortDemo q = new QuickSortDemo(); 7 q.quickSortCore(arr,0,arr.length-1); 8 for(int a : arr){ 9 System.out.print(a+" "); 10 } 11 } 12 private void quickSortCore(int[] arr, int start, int end) { 13 if(start<end){ 14 int sepIndex = partition(arr,start,end); 15 // System.out.println(sepIndex); 16 quickSortCore(arr, start, sepIndex-1); 17 quickSortCore(arr, sepIndex+1, end); 18 } 19 20 } 21 //分开 22 private int partition(int[] arr, int start, int end) { 23 int key = arr[start]; 24 int tmp = 0; 25 while(start < end){ 26 while((start < end) &&(key<= arr[end]) ){ 27 end --; 28 } 29 // 交换时,一定是 start 与 end 相交换 30 if(start<end){ 31 tmp = arr[end]; 32 arr[end] = arr[start]; 33 arr[start] = tmp; 34 start++; 35 } 36 while((start< end) &&(key>= arr[start])){ 37 start++; 38 } 39 if(start<end){ 40 tmp = arr[start]; 41 arr[start] = arr[end]; 42 arr[end] = tmp; 43 end--; 44 } 45 }// start == end 46 // arr[start] = key;// 可不加 47 return start; 48 } 49 50 }
注意:1) 交换时是 start 与 end 相交换,与 key是无关的。以上的代码应是最慢的quickSort; 2) 快排是不稳定的排序方法,空间复杂度为O(logN)
2、归并排序(稳定的排序方法,空间复杂度为O(n))
1 package com.sort; 2 3 import java.util.Arrays; 4 5 public class MergSortDemo { 6 public static void main(String[] args) { 7 int[] arr = { 8, 9, 8, 8, 9, 1, 1 }; 8 MergSortDemo m = new MergSortDemo(); 9 m.mergeSort(arr); 10 System.out.println(Arrays.toString(arr)); 11 } 12 13 public void mergeSort(int[] arr) { 14 int[] tmp = new int[arr.length]; 15 mergeSortCore(arr, 0, arr.length - 1, tmp); 16 } 17 18 public void mergeSortCore(int[] arr, int start, int end, int[] tmp) { 19 20 if (start < end) { 21 int mid = (end - start) / 2 + start; 22 mergeSortCore(arr, start, mid, tmp); 23 mergeSortCore(arr, mid+1, end, tmp); 24 merge(arr, start, mid , end); 25 } 26 } 27 28 // / arr[start...mid] 与 arr[mid+1,... end] ; 两个有序的子数组进行归并 29 private void merge(int[] arr, int start, int mid, int end) { 30 int s = start; 31 int m = mid + 1; 32 // int e = end; 33 int[] tmp = new int[end - start + 1]; 34 int index = 0; 35 // 处理共同的 36 while (s <= mid && m <= end) { 37 while (s <= mid && arr[s] <= arr[m]) { 38 tmp[index++] = arr[s++]; 39 } 40 while (m <= end && arr[s]> arr[m]) { 41 tmp[index++] = arr[m++]; 42 } 43 } 44 // 处理剩下的 45 while (s <= mid) { 46 tmp[index++] = arr[s++]; 47 } 48 while (m <= end) { 49 tmp[index++] = arr[m++]; 50 } 51 for (int i = start, j = 0; i <= end; i++) { 52 arr[i] = tmp[j++]; 53 } 54 } 55 56 }
1 def mergeSort(arr,start,end): 2 if start > end: 3 return 4 if(start < end): 5 mid = (end - start)//2 + start 6 mergeSort(arr,start,mid) 7 mergeSort(arr,mid+1,end) 8 merge(arr,start,mid,end) 9 10 def merge(arr,start,mid,end): 11 # i =start,j = mid+1 ## python 中千万不要这样赋值!! 12 i = start 13 j = mid + 1 14 # print(str(start) + ‘..‘+ str(end)) 15 tmp = [] 16 while(i<=mid and j<=end): 17 if(arr[i] <= arr[j]): 18 tmp.append(arr[i]) 19 i = i+1 20 else: 21 tmp.append(arr[j]) 22 j = j + 1 23 if(i<= mid): 24 tmp.extend(arr[i:mid+1]) 25 if(j <= end): 26 tmp.extend(arr[j:end+1]) 27 arr[start:end+1] = tmp 28 del tmp 29 return arr 30 mergeSort(arr,0,len(arr)-1) 31 # merge(arr,0, (len(arr)-1)//2, len(arr)-1) 32 print(arr)
3、堆排序(不是稳定的排序方法)(下期)
扩展:
1)求数组中第K小的数
思想:利用快排的思想,随机选择元素 t , 它将数组分成两部分,小于 t 的 和大于 t 的; 分别计为 a[0...m-1] ; a[m+1,...n-1];
若 m = k -1 ;则返回 t ;
若 m> k-1 ,说明 第k小的值在a[0...m-1];则求a[0...m-1]中第K小的值;
若 m< k-1 ,说明 第k小的值在a[m+1,...n-1],则在a[m+1,...n-1] 求 k-m小的数。 // 在代码中应是与 下标相比较,所以左右都是K,都是K
平均时间复杂度O(N)
1 def getKthSmall(arr,start,end,k): 2 s = start 3 e = end 4 key = arr[s] 5 while(s < e): 6 while(s < e and key <= arr[e]): 7 e -= 1 8 if key > arr[e]: 9 arr[s] ,arr[e] = arr[e], arr[s] 10 while(s < e and key > arr[s]): 11 s += 1 12 if key < arr[s]: 13 arr[s], arr[e] = arr[e], arr[s] 14 print(‘start = %d; end = %d s = %d‘ % (start, end,s)) 15 if s == k-1: 16 return s 17 elif s > k-1: 18 return getKthSmall(arr,start,s-1,k) 19 else: 20 ## getKthSmall(arr,s+1,end, k-s-1), 不是这个,不是这个,不是这个, 21 ## 因为 我们是与下标比较,所以都是K, 22 return getKthSmall(arr,s+1,end,k) 23 24 arr = [33,3,4,6,32] 25 index = getKthSmall(arr,0,len(arr)-1,3) 26 print(arr[index])
2) 求数组中的逆序数问题
给定一个数组A[0,...N-1] ,若对于两个元素a[i],a[j] ,若 i<j 且 a[i] >a[j] ,则称(a[i],a[j])为逆序对。
如数组 2,56,2,7的逆序数为 3. 归并排序图解如下,在合并时,都可用来计算其逆序对的数。
1 package com.sort; 2 3 public class 逆序对数 { 4 static Integer count = 0; 5 public static void main(String[] args) { 6 int[] arr = { 3, 56, 2, 7 }; 7 mergeSort(arr, 0, arr.length - 1); 8 System.out.println(count); 9 } 10 11 private static void mergeSort(int[] arr, int start, int end) { 12 if (start < end) { 13 int mid = (end - start) / 2 + start; 14 mergeSort(arr, start, mid); 15 mergeSort(arr, mid + 1, end); 16 merge(arr, start, mid, end); 17 } 18 } 19 20 private static void merge(int[] arr, int start, int mid, int end) { 21 // System.out.println(".......2............"); 22 int i = start, j = mid + 1; 23 int k = 0; 24 int[] tmp = new int[end - start + 1]; 25 while (i <= mid && j <= end) { 26 if (i <= mid && arr[i] < arr[j]) { // if (i <= mid && arr[i] <= arr[j]) 27 tmp[k++] = arr[i++]; 28 }else{ // if (j <= end && arr[i] > arr[j]) 29 count += (mid - i + 1); // 主要在这一块地方求!!,别注意条件,前没有=, 30 //这也很好理解,有等于号,也是有逆序数对的。 31 tmp[k++] = arr[j++]; 32 33 } 34 } 35 while (i <= mid) { 36 tmp[k++] = arr[i++]; 37 } 38 while (j <= end) { 39 tmp[k++] = arr[j++]; 40 } 41 k = 0; 42 for (int t = start; t <= end; t++) { 43 arr[t] = arr[k++]; 44 } 45 // System.out.println("..================............"); 46 } 47 48 }
即,如下图所示,在求 逆序对时,两个有序合并时, count += (mid- i + 1);另要注意 arr[i] 等于 arr[j] 时,也是有逆序对的。注意 判断的条件!!
附其它O(n**2)的排序算法
直接插入排序(稳定的排序方法):
1 def straightInsertSort(arr): 2 for i in range(1,len(arr)): ## [1,....len(arr)-1 ]个元素 3 tmp = arr[i] 4 j = i -1 5 while j>=0 : ## 与 [i-1,....0]号元素相比较 6 if(arr[j]> tmp): 7 arr[j+1] = arr[j] 8 j = j-1 9 else: 10 break 11 ## 跳出时 j==0 或 arr[j] <= tmp 12 arr[j+1] = tmp
下期:堆排序,桶排序的运用
参考:
原文地址:https://www.cnblogs.com/vincentbnu/p/9452268.html
时间: 2024-11-05 18:45:38