一、插入排序1、基本思想插入排序(以升序为例)的基本操作是将一个数插入到一个已经排好序的数据序列中,插入后的数据序列是有序的并且元素个数加一。
插入排序的主要思想是:假设要排序的数组为A[]元素个数为n,将这个数组分为两个部分前n-1个元素和最后一个元素,将最后一个元素插入到已经排好序的n-1个元素中的合适的位置。
InsertSort(A[n]) //对A[n]进行插入排序{for i=1 to ndivide(A[i-1],a[i]) //将A[i]分为两部分,前i-1个元素和最后一个元素Insert(a[i],A[i-1])//将最后一个元素插入到排好序的前i-1个元素中}2、算法复杂度分析插入排序存在着最好情况和最坏情况,最好的情况是已经是排好序的了,这时只需比较n-1次即可;最坏的情况是序列是降序的需要排成升序的,那么此时就需要比较n(n-1)/2。
插入排序的赋值操作是比较操作的次数加上n-1次。
平均来说插入排序的算法复杂度为O(n2)。
3、编程实现public static void InsertSort(int[] A){for(int i=1;i<A.length;i++){int temp=A[i];//存储要插入的元素int j=i;//将temp与A[j-1]中的数进行比较,插入到合适的位置while(j>0&&A[j-1]>=temp){A[j]=A[j-1];j--;}A[j]=temp;}}二、冒泡排序1、基本思想冒泡排序(以升序为例)的基本思想是:依次比较相邻的两个数,将小数放在前面,大数放在后面,第一轮比较后,最大的数便被放到了最后;第二轮操作前n-1个数据(假设有n个数据),依然是依次比较相邻的两个数,将小数放在前面,大数放在后面,倒数第二个数便是第二大的数;同理第i轮操作前n-i+1的数据(假设i取值是从1开始的),则n-i+i位置上的数据为第i大的数据。
一共有n-1轮,第i轮比较中共比较n-i次比较。
BubbleSort(A[n]){for(i=1;i<n;i++)for(j=0;j<n-i;j++)if(A[j]>A[j+1]) A[j]?A[j+1];//交换次序}2、算法复杂度分析一共有次比较,最好情况下没有赋值运算,而最坏的情况下有3次赋值运算,因此该算法复杂度为O(n2)。
3、编程实现排序后的结果为升序public static void BubbleSort(int[] A){int temp=0;for (int i = 1; i < A.length ; i++) {for (int j = 0; j < A.length - i ; j++){//将大数往后放if (A[j]>A[j + 1]){temp=A[j];A[j]=A[j + 1];A[j + 1]=temp;}}}}4、改进的冒泡排序算法若冒泡排序在某轮循环中已经排好了序,此时就不需要进行下一轮的循环。
因此改进的方法是对在比较中是否发生数据交换进行标识。
如设置一个布尔量flag,进行比较前将其值设置为true,若发生了数据交换则将flag设置为false,一轮比较完成后,判断flag的值为true 则结束排序,否则进行下一轮的比较。
改进后的冒泡排序时间复杂度为O(n2)。
public static void BubbleSort(int[] A){int temp=0;for (int i = 1; i < A.length &&flag=false; i++) {boolean flag=true;for (int j = 0; j < A.length - i +1; j++){//将大数往后放if (A[j]>A[j + 1]){temp=A[j];A[j]=A[j + 1];A[j + 1]=temp;flag=false;}}}}三、堆排序1、基本思想堆排序的基本思想是:首先将待排序的记录序列构造成一个堆,这时堆的头结点既是最大元素,将其和最后一个记录交换;然后将除了最后一个记录的记录序列再调整成堆,这样就找出了次大的元素,以此类推,直到堆中只有一个记录为止。
调整堆的思想是将待调整的结点的左右孩子进行比较选出较大的一个和待调整结点进行比较,若待调整结点小则交换,否则调整结束。
创建堆得思想是从第n个结点的父结点开始到第1个结点逐个扫描,每一次扫描将以当前结点为根的子树转换成堆。
HeapSort(A){MakeHeap(A)//构造出一个堆for j←n down to 2 doSwap(A[1],A[j])//交换头结点和最后一个记录Siftdown(A[1,……,int((j-1)/2)] ,1)//调整堆end for}Siftdown(H,i){if 2i>n then exit //若下到了叶子结点则退出repeat i←2i//寻找待下移结点的左右孩子中较大的一个if i+1<=n and H[i+1]>H[i] theni←i+1end if//若待下移结点比左右孩子中较大的一个小则交换if H[int(i/2)]<H[i] thenSwap(H[int(i/2)],H[i])else break //若待下移结点比左右孩子大则调整结束end if}MakeHeap(A){ i←n //总共有n个元素m←int(i/2)for j←m down to 1 //从第n个元素的父结点开始到第1个元素do Sift-down(A[m,m+1,……,n],i) //即父结点小于孩子结点则进行交换end for}2、算法复杂度分析堆排序的时间复杂度主要有构造堆和调整堆这两部分的时间复杂度构成,构造堆的时间复杂度在最坏的情况下是O(n),调整堆的时间复杂度为O(log2n)。
因此堆排序的大致时间复杂度可以写成O(n)+(n-1)(1+O(log2n)),即时间复杂度为O(nlog2n)。
3、编程实现public static void HeapSort(int[] A){//MakeHeap(A)将数组A构建成堆for(int i=A.length/2;i>0;i--)Siftdown(A,i,A.length);//数组A,要下移的元素为A[i]for(int i = A.length ; i >1 ; i--){//交换头结点和最后一个元素int temp=A[1];A[1]=A[i];A[i]=temp;Shiftdown(A, 1,i-1);//调整堆}}private static void shiftDown(int[] A, int i,int n){while(2*i<n){j=2*i;//找出最大的孩子if((j+1<n)&&A[j+1]>A[j])j=j+1;//待下移结点和最大的孩子进行比较,若小则下移否则调整结束if(A[i]<A[j]){int temp=H[i];H[i]=H[j];H[j]=temp;}else break;}}四、合并排序1、基本思想合并排序的基本操作是:首先将待排序序列划分为两个长度相等的子序列;然后分别对两个子序列进行归并排序,得到两个有序的子序列;最后将两个有序的子序列合并成一个有序数列。
MergeSort(A[2*n]){divide A[2*n] into A[1,……,n],A[n-1,……,2*n];//划分MergeSort(A[1,……,n]);//归并排序前半个子序列MergeSort(A[[n-1,……,2*n]);//归并排序后半个子序列Merge;//合并}2、算法复杂度分析合并步的时间复杂度为O(n)。
合并排序算法的时间复杂度为O(nlog2n)。
3、编程实现public int[] MergeSort(int[] A, int[] tempA, int s, int t){//如果序列中有一个以上的元素,即s<t则进行排序if(s < t){int center = (s + t) / 2;MergeSort(A, tempA, s, 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=swhile(i <= m&& j <= t){//取A[i]和A[j]中较小者放入tempA[k]if(A[i]<=A[j]){tempA[k++] = A[i++];}else{tempA[k++] = A[j++];}}if(i<=m)while(i<=m)tempA[k++]=A[i++];//处理前一个子序列else while(j<=t)tempA[k++]=A[j++];//处理后一个子序列return tempA;}五、快速排序1、基本思想快速排序的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
QuickSort(A,first,end){if first<end thenm=Partition(A,first,end)//将数据分割成独立的两部分QuickSort(A,first,m-1)//递归的对左侧子序列进行快速排序QuickSort(A,m+1t,end)//递归的对右侧子序列进行快速排序end if}其中通过一趟排序将要排序的数据分割成独立的两部分的基本操作步骤如下:1)设置两个变量i、j,排序开始的时候:i=fist,j=end;取第一个数组元素作为基准元素。
2)将基准元素和j指向的元素进行比较,如果j指向的元素大则j--;重复直到j指向的元素小并i<j,则将基准元素和j所指向的元素进行交换。
3)将基准元素和i指向的元素进行比较,如果i指向的元素小则i--;重复直到i指向的元素大并i<j,则将基准元素和i所指向的元素进行交换。