1、一、插入排序1、基本思想插入排序(以升序为例)的基本操作是将一个数插入到一个已经排好序的数据序列中,插入后的数据序列是有序的并且元素个数加一。插入排序的主要思想是:假设要排序的数组为 A元素个数为 n,将这个数组分为两个部分前 n-1 个元素和最后一个元素,将最后一个元素插入到已经排好序的 n-1 个元素中的合适的位置。InsertSort(An) /对 An进行插入排序 for i=1 to ndivide(Ai-1,ai) /将 Ai分为两部分,前 i-1 个元素和最后一个元素Insert(ai,Ai-1)/将最后一个元素插入到排好序的前 i-1 个元素中2、算法复杂度分析插入排序存在着最
2、好情况和最坏情况,最好的情况是已经是排好序的了,这时只需比较 n-1 次即可;最坏的情况是序列是降序的需要排成升序的,那么此时就需要比较 n(n-1)/2。插入排序的赋值操作是比较操作的次数加上 n-1 次。平均来说插入排序的算法复杂度为 O(n2)。3、编程实现public static void InsertSort(int A) for(int i=1;i0j-;Aj=temp; 二、冒泡排序1、基本思想冒泡排序(以升序为例)的基本思想是:依次比较相邻的两个数,将小数放在前面,大数放在后面,第一轮比较后,最大的数便被放到了最后;第二轮操作前 n-1 个数据(假设有 n 个数据),依然是依
3、次比较相邻的两个数,将小数放在前面,大数放在后面,倒数第二个数便是第二大的数;同理第 i 轮操作前 n-i+1 的数据(假设 i 取值是从 1 开始的),则 n-i+i 位置上的数据为第 i 大的数据。一共有 n-1 轮,第 i 轮比较中共比较 n-i 次比较。BubbleSort(An)for(i=1;iAj+1) AjAj+1;/交换次序2、算法复杂度分析一共有 次比较,最好情况下没有赋值运算,而最坏的情况下有 3次赋值运算,因此该算法复杂度为 O(n2)。3、编程实现排序后的结果为升序public static void BubbleSort(int A)int temp=0;for (
4、int i = 1; i Aj + 1)temp=Aj;Aj=Aj + 1;Aj + 1=temp;4、改进的冒泡排序算法若冒泡排序在某轮循环中已经排好了序,此时就不需要进行下一轮的循环。因此改进的方法是对在比较中是否发生数据交换进行标识。如设置一个布尔量flag,进行比较前将其值设置为 true,若发生了数据交换则将 flag 设置为 false,一轮比较完成后,判断 flag 的值为 true 则结束排序,否则进行下一轮的比较。改进后的冒泡排序时间复杂度为 O(n2)。public static void BubbleSort(int A)int temp=0;for (int i = 1
5、; i Aj + 1)temp=Aj;Aj=Aj + 1;Aj + 1=temp;flag=false;三、堆排序1、基本思想堆排序的基本思想是:首先将待排序的记录序列构造成一个堆,这时堆的头结点既是最大元素,将其和最后一个记录交换;然后将除了最后一个记录的记录序列再调整成堆,这样就找出了次大的元素,以此类推,直到堆中只有一个记录为止。调整堆的思想是将待调整的结点的左右孩子进行比较选出较大的一个和待调整结点进行比较,若待调整结点小则交换,否则调整结束。创建堆得思想是从第 n 个结点的父结点开始到第 1 个结点逐个扫描,每一次扫描将以当前结点为根的子树转换成堆。HeapSort(A)MakeHe
6、ap(A)/构造出一个堆for jn down to 2 doSwap(A1,Aj)/交换头结点和最后一个记录Siftdown(A1,int(j-1)/2) ,1)/调整堆end forSiftdown(H,i)if 2in then exit /若下到了叶子结点则退出repeat i2i /寻找待下移结点的左右孩子中较大的一个if i+1Hi then ii+1end if/若待下移结点比左右孩子中较大的一个小则交换if Hint(i/2)0;i-)Siftdown(A,i,A.length);/数组 A,要下移的元素为 Aifor(int i = A.length ; i 1 ; i-)/
7、交换头结点和最后一个元素int temp=A1;A1=Ai;Ai=temp;Shiftdown(A, 1,i-1);/调整堆 private static void shiftDown(int A, int i,int n)while(2*iAj)j=j+1;/待下移结点和最大的孩子进行比较,若小则下移否则调整结束if(AiAj)int temp=Hi;Hi=Hj;Hj=temp;else break; 四、合并排序1、基本思想合并排序的基本操作是:首先将待排序序列划分为两个长度相等的子序列;然后分别对两个子序列进行归并排序,得到两个有序的子序列;最后将两个有序的子序列合并成一个有序数列。Me
8、rgeSort(A2*n)divide A2*n into A1,n,An-1,2*n;/划分MergeSort(A1,n);/归并排序前半个子序列MergeSort(An-1,2*n);/归并排序后半个子序列Merge;/合并2、算法复杂度分析合并步的时间复杂度为 O(n)。合并排序算法的时间复杂度为 O(nlog2n)。3、编程实现public int MergeSort(int A, int tempA, int s, int t)/如果序列中有一个以上的元素,即 st 则进行排序if(s t)int center = (s + t) / 2; MergeSort(A, tempA, s
9、, center);/归并排序前半个子序列 MergeSort(A, tempA, center + 1, t);/归并排序后半个子序列 Merge(A,tempA, s, center, t);/合并 return tempA; public int Merge(int A, int tempA, int s, int m, int t) int n = t- s + 1;/n 为数据总个数int i=s;j=m+1;k=s while(i = m else tempAk+ = Aj+; if(i=m) while(i=m)tempAk+=Ai+;/处理前一个子序列else while(j=
10、t)tempAk+=Aj+;/处理后一个子序列 return tempA; 五、快速排序1、基本思想快速排序的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。QuickSort(A,first,end)if firstend thenm=Partition(A,first,end)/将数据分割成独立的两部分QuickSort(A,first,m-1)/递归的对左侧子序列进行快速排序QuickSort(A,m+1t,end)/递归的对
11、右侧子序列进行快速排序end if其中通过一趟排序将要排序的数据分割成独立的两部分的基本操作步骤如下:1)设置两个变量 i、j,排序开始的时候:i=fist,j=end;取第一个数组元素作为基准元素。2)将基准元素和 j 指向的元素进行比较,如果 j 指向的元素大则 j-;重复直到 j 指向的元素小并 ij,则将基准元素和 j 所指向的元素进行交换。3)将基准元素和 i 指向的元素进行比较,如果 i 指向的元素小则 i-;重复直到 i 指向的元素大并 ij,则将基准元素和 i 所指向的元素进行交换。4)重复第 2、3 步,直到 i=j;2、算法复杂度分析在最好的情况下,每次划分后左侧子序列和右
12、侧子序列的长度相同。在有n 个元素的数组中,一次划分需要的时间是 O(n),而每次划分后,正好为长度相等的两个子序列,因此有 ,因此时间复杂度为 O(nlog2n)。在最坏的情况下,待排序数组为升序或逆序排列,则每次划分只得到比上一次少一个元素的子序列(另一个为空)。此时必须经过 n-1 次递归调用,且第 i 次划分需要比较 n-i 次才能找到基准位置。因此时间复杂度为 O(n2)在平均情况下, ( )。用归纳法证明知时间复杂度也为 O(nlog2n)。3、编程实现public static void QuickSort(int A,int first,int end)if(firstend)m=Partition(A,first,end);QuickSort(A,first,m-1);QuickSort(A,m+1,end);public int Partition(int A,int fist,int end)int i=fist;j=end;int temp;while(ij)while(ijif(ij)temp=Ai;Ai=Aj;Aj=temp;i+;while(ijif(ij)temp=Ai;Ai=Aj;Aj=temp;j-;return i;