您的位置:首页 > 理论基础 > 数据结构算法

数据结构 JAVA描述(十二) 归并排序 链式基数排序

2016-01-05 17:13 211 查看

归并排序

/**
* @description 2-路归并排序算法  归并过程中引入数组temp[],第一趟由a归并到temp,第二趟由temp归并到a,如此反复直到n个记录为一个有序表
*              返回的是a[]。不论是偶数趟还是奇数趟,最后都会mergepas(temp, a, s, n); 数据都会在a中
* @return
* @author liuquan
* @date  2016年1月5日
*/
public static int[] mergeSort(int[] before){
int[] a= Arrays.copyOf(before, before.length);
int s = 1; //s为已排序的子序列长度
int n = a.length;
int[] temp = new int
;
while(s < n){
mergepas(a, temp, s, n);
s *= 2;
mergepas(temp, a, s, n);
s *= 2;
}
return a;
}

/**
* @description 一趟归并排序的算法
* @param a
* @param b
* @param s s是待归并的有序子序列的长度
* @param n n是待排序序列的长度
* @author liuquan
* @date  2016年1月5日
*/
private static void mergepas(int[] a, int[] b, int s, int n){
int p = 0;  //p为每一对待合并表的第一个元素的下标
//首先两两归并长度均为s的有序表
while(p + 2 * s - 1 <= n - 1){
merge(a, b, p, p + s - 1, p + 2 * s -1);
p += 2 * s;
}
//归并最后两个长度不相等的有序表
if(p * s - 1 < n - 1){
merge(a, b, p, p + s - 1, n - 1);
}
else{ //只剩余一个有序表了,直接复制到b中
for(int i = p; i <= n - 1; i++){
b[i] = a[a];
}
}
}

/**
* @description 把两个相邻的有序表a[h……m]和a[m+1……t]归并成一个有序表 b[h……t]
* @author liuquan
* @date  2016年1月5日
*/
private static void merge(int[] a, int[] b, int h, int m, int t){
int i = h, j = m +1, k = h;
//将a中两个相邻子序列归并到b中
while(i <= m && j <= t){
if(a[i] <= a[j]){
b[k++] = a[i++];
}
else{
b[k++] = a[j++];
}
}
//将剩余子序列复制到b中
while(i <= m){
b[k++] = a[i++];
}
while(j <= t){
b[k++] = a[j++];
}
}


算法性能分析

空间复杂度:O(n),存在一个辅助数组

时间复杂度:归并趟数为[㏒₂ n],而每一对有序序列的归并时的比较次数均不大于记录的移动次数,而记录的移动次数=n,所以时间复杂度是O(n ㏒₂ n)

算法稳定性:稳定

基数排序

假设n个记录的排序表中的每个记录包含d个关键字{k1,k2,……kd},排序的有序表是指表中任意两个记录a[i]和a[j]都满足有序关系:

(ki1,ki2,ki3……kid) < (kj1,kj2……kjd)

其中k1称为最主位关键字,kd称为最次位关键字

多关键字的排序有两种:

最主位优先(Most Significant Digit First),简称MSD法

最次位优先(Least Significant Digit First),简称LSD法

链式基数排序

在基数排序中,常使用d表示关键字的位数,用rd表示关键字可取值的种类数,例如:关键字为一个3位数,则d = 3,每一个关键字为数字,rd=10.

执行基数排序可采用链表的存储结构,用一个长度为n的单链表r存放待排序的n个记录,再使用两个长度为rd的一维数组f和e,分别存放rd个队列中指向队首结点和队尾结点的指针:

形成初始链表

将最小的关键字值作为当前关键字,即i=d

执行第i趟分配和收集。链头和链尾分别由f[0……rd-1]和e[0……rd-1]指向,再将这rd个子序列头尾相连形成一个新的当前处理序列。

将当前关键字向高位推进一位,即i = i-1;重复执行上面步骤,直到d位关键字处理完毕。

算法性能分析

空间复杂度: 2*rd个队首和队尾的辅助空间,n个链表指针

时间复杂度:O(d(n+rd))

其中一趟分配的时间复杂度为0(n),一趟收集的时间复杂度为O(rd),共进行了d趟分配和收集,所以时间复杂度是O(d(n+rd))

算法稳定性:稳定
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息