public class Sort{
/**
*冒泡排序(由小到大)
*思路:对于给定的n个记录,从最后一个记录开始依次对相邻的两个记录进行比较,当后面的记录小于前面的记录时,交换位置,
*进行一轮比较和换位之后,n个记录中的最小记录位于第1位;然后对后n-1个记录进行第二轮比较;重复该过程直到进行比较的记录只剩下一个为止.
*/
public void bubble_sort(int [] a){
for(int i = 0;i < a.length;i++){
for(int j = a.length - 1;j > i;j--){
if(a[j] < a[j-1]){
int temp = a[j];
a[j] = a[j-1];
a[j-1] = temp;
}
}
}
}
/**
*选择排序(由小到大)
*思路:对于给定的一组记录,经过第一轮比较之后得到最小的记录,然后将该记录与第一个记录的位置交换;
*接着对不包括第一个记录的其他记录进行第二轮比较,得到最小记录并与第二个记录进行位置交换;
*重复该过程,直到进行比较的记录只有一个为止.
*/
public void select_sort(int [] a){
for(int i = 0;i < a.length;i++){
int min = a[i];
int flag = i;
for(int j = a.length - 1;j > i;j){
if(a[j] < min){
min = a[j];
flag = j;
}
}
if(flag != i){
a[flag] = a[i];
a[i] = min;
}
}
}
/**
*插入排序(由小到大)
*思路:对于给定的一组记录,初始时假设第一个记录自成一个有序序列,其余记录为无序序列;
*接着从第二个记录开始,按照记录的大小依次将当前处理的记录插入到其之前的有序序列中,直到最后一个记录插入到有序序列中为止.
*/
public void insert_sort(int [] a){
for(int i = 1;i < a.length;i++){
if(a[i] < a[i-1]){
int temp = a[i];
int j = i;
while(j >= 1 && a[j-1] > temp){
a[j] = a[j-1];
j -- ;
}
a[j] = temp;
}
}
}
/**
*希尔排序(由小到大)
*思路:先将待排序的数组元素分成多个子序列,使得每个子序列的元素个数相对较少,然后对各个子序列分别进行直接插入排序,
* 待整个待排序序列"基本有序"后,最后对所有元素进行一次直接插入排序.
*希尔排序步骤:
*1.选择一个步长序列t1,t2,...,tk,满足ti>tj(i<j),且tk=1;
*2.按步长序列个数k,对待排序序列进行k趟排序;
*3.每趟排序,根据对应的步长ti,将待排序列分割成ti个子序列,分别对各个子序列进行直接插入排序.
*/
public void shell_sort(int [] a){
int len = a.length;
for(int h = len/2;h > 0;h = h/2){//h表示步长
for(int i = h;i < len;i++){
if(a[i] < a[i-h]){
int temp = a[i];
int j = i;
while(j >= h && a[j-h] > temp){
a[j] = a[j-h];
j = j-h;
}
a[j] = temp;
}
}
}
}
/**
*堆排序(由小到大)
*思路:对于给定的n个记录,初始时把这些记录看作一颗顺序存储的二叉树,然后将其调整为一个大顶堆,
* 然后将堆的最后一个元素与堆顶元素(即二叉树的根节点)进行交换后,堆的最后一个元素即为最大记录;
* 接着将前n-1个记录(即不包括最大记录)重新调整为一个大顶堆,再将堆顶元素与当前堆的最后一个元素进行交换后得到次最大记录;
* 重复该过程直到调整的堆中只剩一个元素为止,即该元素为最小记录,此时得到一个有序序列.
*简化思路:1.建立大顶堆2.交换第一个元素与最后一个元素的值3.重复以上步骤,不过每次参与建堆的元素个数比上一次减一
*/
public void heap_sort(int [] a){
int len = a.length;
for(int i = len/2;i >= 0;i--){//从下往上,从右往左建立初始大顶堆
heap_adjust(a,i,len-1);
}
for(int i = len-1;i > 0;i--){
int temp = a[0];
a[0] = a[i];
a[i] = temp;
head_adjust(a,0,i-1);
}
}
public void heap_adjust(int [] a,int parent,int len){
int temp = a[parent];
for(int i = 2*parent + 1;i <= len;i = 2*i + 1){
if(i+1 <= len && a[i+1] > a[i]){
i = i + 1;
}
if(a[i] < temp){
break;
}
a[parent] = a[i];
a[i] = temp;
parent = i;
}
}
/**
*归并排序(由小到大)
*思路:对于给定的n个记录,首先将每两个相邻长度为1的子序列进行归并,得到n/2(向上取整)个长度为2或1的有序子序列,再将其两两归并,
*反复执行此过程,直到得到一个有序序列.
*归并排序的关键两步:1.划分半子表2.合并半子表
*/
public void merge_sort(int [] a){
for(int gap = 1;gap <= a.length/2;gap = gap*2){
merge_sort1(a,gap);
}
}
public void merge_sort1(int [] a,int gap){
int i;
for(i = 0;i + 2*gap-1 < a.length;i = i + 2*gap){
merge(a,i,i+gap,i+2*gap-1);
}
if(i + gap < a.length){
merge(a,i,i+gap,a.length-1);
}
}
public void megre(int [] a,int low,int mid,int high){
if(low >= mid || mid > high) return ;
int i = low,j = mid;
int n = 0;
int [] temp = new int [high - low + 1];
while(i < mid && j <= high){
if(a[i] <= a[j]){
temp[n++] = a[i++];
}else{
temp[n++] = a[j++];
}
}
while(i < mid){
temp[n++] = a[i++];
}
while(j <= high){
temp[n++] = a[j++];
}
for(int k=0;k < temp.length;k++){
a[k+low] = temp[k];
}
}
/**
*快速排序(由小到大)
*思路:对于给定的n个记录,通过一趟排序之后,将原序列分为两部分,其中前一部分的所有记录均比后一部分的所有记录小,
* 然后再依次对前后两部分的记录进行快速排序,递归该过程,直到序列中所有记录均有序为止.
*算法步骤:
*1.分解,将输入的序列a[m...n]划分为两个非空子序列a[m...k]和a[k+1...n],使a[m...k]中任一元素的值不大于a[k+1...n]中的任一元素的值;
*2.递归求解,通过递归调用快速排序算法分别对a[m...k]和a[k+1...n]进行排序;
*3.合并:由于分解出的两个子序列的排序是就地进行,所以在a[m...k]和a[k+1...n]都排好序后不需要执行任何计算,a[m...n]就已经排好序.
*/
public vodi quick_sort(int [] a){
quick_sort1(a,0,a.length-1);
}
public void quick_sort1(int [] a,int start,int end){
if(start >= end) return ;
int pivot = partition(a,start,end);
quick_sort1(a,start,pivot-1);
quick_sort1(a,pivot+1,end);
}
public int partition(int [] a,int start,int end){
int temp = a[start];
int left = start,right = end;
while(left < right){
while(right>left && a[right] >= temp){
right-- ;
}
if(right > left){
a[left] = a[right];
a[right] = temp;
}
while(left < right && a[left] <= temp){
left++;
}
if(left < right){
a[right] = a[left];
a[left] = temp;
}
}
return left;
}
/**
*计数排序(由小到大)
*思路:用待排序的数作为计数数组的下标,统计每个数字的个数,然后依次输出即可得到有序序列.
*算法步骤:
*1.找出待排序的数组中最大的元素;
*2.统计数组中每个值为i的元素出现的次数,存入数组C的第i项;
*3.反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1.
*/
public void count_sort(int [] a){
if(a == null || a.length == 0) return ;
//找到待排序数组的最大值
int max = a[0];
for(int i = 1;i < a.length;i++){
if(a[i] > max){
max = a[i];
}
}
int [] c = new int [max+1];
for(in i = 0;i < a.length;i++){
c[a[i]]++;
}
//计数排序
int k = 0;
for(int i = 0;i < max+1;i++){
while(c[i] != 0){
a[k++] = i;
c[i]--;
}
}
}
/**
*桶排序(由小到大)
*思路:桶排序是计数排序的升级版.假设输入数据服从均匀分布,将数据分到有限数量的桶里,每个桶再分别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排).
*算法步骤:
*1.设置一个定量的数组当作空桶;
*2.遍历输入数据,并且把数据一个一个放到对应的桶里去;
*3.对每个不是空的桶进行排序;
*4.从不是空的桶里把排好序的数据拼接起来.
*/
public void bucket_sort(int [] a){
if(a == null || a.length == 0) return ;
int bucketNums = 10;//这里默认10,规定待排数[0,100)
//桶的索引
ArrayList<LinkedList<Integer>> buckets = new ArrayList<>();
for(int i = 0;i < bucketNums;i++){
//使用链表比较合适
buckets.add(new LinkedList<Integer>());
}
//划分桶
for(int i = 0;i < a.length;i++){
buckets.get(f(a[i])).add(a[i]);
}
//对每个桶进行排序
for(int i = 0;i < bucketNums;i++){
if(!buckets.get(i).isEmpty()){
Collections.sort(buckets.get(i));//快速排序
}
}
//还原排好序的数组
int k = 0;
for(LinkedList<Integer> bucket : buckets){
if(!bucket.isEmpty()){
for(int elem : bucket){
a[k++] = elem;
}
}
}
}
//桶的映射函数
public int f(int n){
return n/10;
}
/**
*基数排序(由小到大)
*思路:基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。
*算法步骤:
*1.取得数组中的最大数,并取得位数;
*2.a为原始数组,从最低位开始取每个位组成radix数组;
*3.对radix进行计数排序(利用计数排序适用于小范围数的特点).
*/
public void radix_sort(int [] a){
if(a == null || a.length == 0) return ;
int maxBit = getMaxBit(a);//得到最大位数
for(int i = 1;i <= maxBit;i++){
ArrayList<LinkedList<Integer>> buf = distribute(a,i);//分配
collect(a,buf);//收集
}
}
//获取最大位数
public int getMaxBit(int [] a){
int max = 0;
for(int elem : a){
int len = (elem + "").length();
if(len > max) max = len;
}
return max;
}
//分配
public ArrayList<LinkedList<Integer>> distribute(int [] a,int iBit){
ArrayList<LinkedList<Integer>> buf = new ArrayList<>();
for(int i = 0;i < 10;i++){
buf.add(new LinkedList<Integer>());
}
for(int i = 0;i < a.length;i++){
buf.get(getNBit(a[i],iBit)).add(a[i]);
}
return buf;
}
public int getNBit(int x,int n){//获取x的第n位,如果没有则为0
String sx = x + "";
if(sx.length() < n){
return 0;
}else{
return sx.charAt(sx.length() - n) - '0';
}
}
//收集
public void collect(int [] a,ArrayList<LinkedList<Integer>> buf){
int k = 0;
for(LinkedList<Integer> bucket : buf){
if(!bucket.isEmpty()){
for(int elem : bucket){
a[k++] = elem;
}
}
}
}
}
排序算法
最新推荐文章于 2024-10-16 23:20:52 发布