1.归并排序与选择排序
归并排序定义:归并排序就是将两个或两个以上的有序表合并成一个有序表的过程。将两个有序表合并成一个有序表的过程称为2-路归并。
选择排序定义:每一趟从待排序的记录中选出关键字最小的记录,按顺序放在已排序的记录序列的最后,直到全部排完为止。
注意:1.选择是把一个文件分成包含k个最小元素和n-k个最大元素的两个部分的过程。
2.选择和归并互为逆操作:选择是把一个序列分成两部分,归并把两个文件合并成一个文件
3.归并排序是快速排序的补充
4.归并排序以连续的方式访问数据
5.归并排序适用于链表排序。
6.归并排序对输入的初始次序不敏感。
2.归并排序全过程
(画图功力不行,还是贴图吧,,,,)
此时,比较结束后,把A中左项或子项剩余的元素整体复制到B中去,排序完成。
排序算法如下:
void Merge(SqList L,int low,int m,int high)
{
int B[high-low+1];
int i=low,j=m+1,k=0;
while(i<=mid&&j<=high)
{
B[k++]=L.elem[i]<=L.elem[j]?L.elem[i++]:L.elem[j++];
}
while(i<=mid) B[k++]=L.elem[i++];
while(j<=high) B[k++]=L.elem[j++];
for(i=low,k=0;i<=high;i++)
{
L.elem[i]=B[k++];
}
delete []B;
}
当然这个算法的前提是两个排好序的表合并成一个表,那么如何解决一个乱序表的排序问题呢,其实可以利用递归思想,即把一个乱序表分成两个子序表,再把子序表各自分出两个子子序表,,,直到分到序列表长度为1为止,此时两两进行排序,不断的向回排序。
递归算法:
void MergeSort(SqList L,int low,int high)
{
/*用分治法进行二路归并排序*/
int mid;
if(low<high) /*区间长度大于1*/
{
mid=(low+high)/2; /*分解*/
MergeSort(L,low,mid); /*递归地对low到mid序列排序 */
MergeSort(L,mid+1,high); /*递归地对mid+1到high序列排序 */
Merge(L,low,mid,high); /*归并*/
}
}
3.
归并排序分析:
归并排序将输入序列分成两部分并递归地处理每一部分。当子问题解决后,算法又将子问题地解合并。假设具有n个元素地归并排序地复杂度表示为T(n),则归并排序的递归式可定义为:
T(n)=2T(n/2)+O(n);
根据分治法主定理:T(n)=O(nlogn)
4.性能
最坏情况下时间复杂度:O(nlogn)
最好情况下时间复杂度:O(nlogn)
平均情况下时间复杂度:O(nlogn)
最坏情况下空间复杂度:O(n)辅助
选择排序:
选择排序是一种原地排序算法,适用于小文件,由于选择操作是基于键值的且交换操作只在需要时才执行,所以选择排序常用于数值较大和键值较小的文件。
优点:容易实现,原地排序不需要额外的存储空间
缺点:扩展性较差:O(n^2)
算法:
1.寻找序列中的最小值。
2.用当前位置的值交换最小值。
3.对于所有元素重复上述过程,直到整个序列排序完成。
void Selection(int A[],int n)
int i,j,min,temp;
for(i=0;i<n-1;i++)
{
min=i;
for(j=i+1;j<n;j++)
{
if(A[j]<A[min])
{
min=j;
}
temp=A[min];
A[min]=A[i];
A[i]=temp;
}
}
最坏情况时间复杂度:O(n^2)
最好情况时间复杂度:O(n)
最坏情况下空间复杂度:O(1)
附归并排序Java代码
package cn.sal.paixu;
import java.util.Arrays;
public class MergeSort {
public static void mergeSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
mergeSort(arr, 0, arr.length - 1);
}
public static void mergeSort(int[] arr, int l, int r) {
if (l == r) {
return;
}
int mid = l + ((r - l) >> 1);
mergeSort(arr, l, mid);
mergeSort(arr, mid + 1, r);
merge(arr, l, mid, r);
}
public static void merge(int[] arr, int l, int m, int r) {
int[] help = new int[r - l + 1];
int i = 0;
int p1 = l;
int p2 = m + 1;
while (p1 <= m && p2 <= r) {
help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
}
while (p1 <= m) {
help[i++] = arr[p1++];
}
while (p2 <= r) {
help[i++] = arr[p2++];
}
for (i = 0; i < help.length; i++) {
arr[l + i] = help[i];
}
}
// for test
public static void comparator(int[] arr) {
Arrays.sort(arr);
}
// for test
public static int[] generateRandomArray(int maxSize, int maxValue) {
int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
}
return arr;
}
// for test
public static int[] copyArray(int[] arr) {
if (arr == null) {
return null;
}
int[] res = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
res[i] = arr[i];
}
return res;
}
// for test
public static boolean isEqual(int[] arr1, int[] arr2) {
if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
return false;
}
if (arr1 == null && arr2 == null) {
return true;
}
if (arr1.length != arr2.length) {
return false;
}
for (int i = 0; i < arr1.length; i++) {
if (arr1[i] != arr2[i]) {
return false;
}
}
return true;
}
// for test
public static void printArray(int[] arr) {
if (arr == null) {
return;
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
// for test
public static void main(String[] args) {
int testTime = 500000;
int maxSize = 100;
int maxValue = 100;
boolean succeed = true;
for (int i = 0; i < testTime; i++) {
int[] arr1 = generateRandomArray(maxSize, maxValue);
int[] arr2 = copyArray(arr1);
mergeSort(arr1);
comparator(arr2);
if (!isEqual(arr1, arr2)) {
succeed = false;
printArray(arr1);
printArray(arr2);
break;
}
}
System.out.println(succeed ? "Nice!" : "Fucking fucked!");
int[] arr = generateRandomArray(maxSize, maxValue);
printArray(arr);
mergeSort(arr);
printArray(arr);
}
}