排序算法汇总与实现
1.插入排序
问题描述:
输入:n个数( a 1 , a 2 , . . . . , a n a_1,a_2,....,a_n a1,a2,....,an)
输出:输入序列的一个排序(即重新排序)( a 1 ′ , a 2 ′ , . . . a n ′ a_1',a_2',...a_n' a1′,a2′,...an′),使得 a 1 ′ ≤ a 2 ′ ≤ a 3 ′ , . . . ≤ a n ′ a_1' \leq a_2' \leq a_3',... \leq a_n' a1′≤a2′≤a3′,...≤an′
思想:模拟打牌插序过程。输入的各数字是原地排序的(sorted in place),即这些数字就是在数组A中进行重新排序的,在任何时刻,至多只有其中的常数个数字是存储在数组之外的。数组被分为两部分A[1,j-1]的子数组构成左手中当前已排序好的牌(数组),元素A[j+1,n]对应仍然乱序的牌(数组)。j从2开始,每次讲A[j+1]插入A[1,j-1]数组中,经过外循环n次loop,完成排序。
例子:[5,2,4,6,1,3]
- 当j=2时,排序顺序为[5|2,4,6,1,3] |左边为已经排好顺序的序列
- 当j+1,5>2,所以排序序列变为[2,5|4,6,1,3]
- 2<4<5,所以[2,4,5|6,1,3]
- 5<6,[2,4,5,6|1,3]
- 1<2,[1,2,4,5,6|3]
- 2<3<4,[1,2,3,4,5,6]
代码实现:
def insertSoted(A:[int]):
l = len(A)
for j in range(1,l):
key = A[j]
i = j - 1
while i >= 0 and A[i] > key: #往子数组中插入,第二层循环
A[i+1] = A[i]
i = i -1
A[i+1] = key
return A
if __name__=='__main__':
A = [5,2,4,6,1,3]
d = insertSoted(A)
package joe.sorted;
import java.util.Arrays;
public class insertSoted {
public static void main(String[] args){
Integer[] integerArray = new Integer[]{
5,2,4,6,1,3};
insertSoted(integerArray);
System.out.println(Arrays.toString(integerArray));
}
public static void insertSoted(Integer[] A){
int i,j,key;
int l = A.length;
for (j=1;j<l;j++){
key = A[j];
i = j-1;
while (i>= 0 && A[i] > key){
A[i+1] = A[i];
i = i - 1;
}
A[i+1] = key;
}
}
}
算法复杂度:
算法经历了2次循环,所以时间复杂度为: O ( n 2 ) O(n^2) O(n2)
2.合并排序
有很多算法在结构上是递归的:为了解决一个给定的问题,算法要一次或多次地递归调用其自身来解决相关的子问题。这些算法通常采用分治策略。
分治策略:将原问题划分为 n n n个规模较小而结构与原问题相似的子问题;递归地解决这些子问题,然后再合并其结果,就得到原问题的解。
分治模式在每一层递归都有三个步骤:
分解(Divide):将原问题分解为一系列子问题
解决(Conquer):递归地解决各个子问题。若子问题足够小,则直接求解
合并(Combine):将子问题的结果合并成原问题的解。
合并排序:
分解:将 n n n个元素分成包含n/2个元素的子序列
解决:用合并排序法对两个子序列递归地排序
合并:合并两个已排序的子序列以得到的排序结果
在对子序列排序时,其长度为1时递归结束。单个元素被视为是已排序好的
关键步骤:合并两个已排序的子序列。为做合并,引入一个辅助过程MERGE(A,p,q,r),其中A:数组,p,q,r:下标。满足 p ≤ q ≤ r p \leq q \leq r p≤q≤r。该过程假设子数组A[p,q]和A[q+1,r]都已排序好,将其合并成一个已排序好的数组。
算法实现:
Java
package joe.sorted;
import org.apache.avro.generic.GenericData;
import java.util.Arrays;
public class mergeSorted {
public static void sort(Integer[] A, int left, int right){
if(left>=right){
return;
}
int mid = (left+right)/2;
System.out.println(left+','+mid+','+','+right+"dsfa");;
sort(A,left,mid);
sort(A,mid+1,right);
merge(A,left,mid,right);
}
private static Integer[] merge(Integer[] A, Integer left, Integer mid, Integer right) {
int i;
int j;
int n1 = mid-left+1;
int n2 = right-mid;
int[] L = new int[n1+1];
int[] R = new int[n2+1];
System.out.print(R.length+"sdf"+L.length);
for (i=0;i<n1;i++){
L[i] = A[left+i];
}
for(j=0;j<n2;j++){
R[j] = A[mid+j+1];
}
L[n1] = (int)Double.POSITIVE_INFINITY; //重要
R[n2] = (int)Double.POSITIVE_INFINITY;
i = 0;
j = 0;
//System.out.println(Arrays.toString(L));
for(int k=left;k<=right;k++){
//System.out.println(R[j]);
if(L[i]<=R[j]){
A[k] = L[i];
i++;
}
else {
A[k] = R[j