用java实现并归排序,快速排序,堆排序,冒泡排序,插入排序
import java.util.Arrays;
public class TestSort{
private static int[] arr={34,12,54,1,5};
private static int len=arr.length;
private static void swap(int i,int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void main(String[] args){
// bubblingSort();
// quickSort(0,arr.length-1);
//int[] result = new int[len];
// merge_sort_recursive(result,0,len-1);
merge_sort();
System.out.println(Arrays.toString(arr));
}
/**
* 选择排序
*/
public static void selectionSort() {
int i, j, min, temp;
for (i = 0; i < len - 1; i++) {
min = i;//未排序序列中最小数据数组下标
for (j = i + 1; j < len; j++)//在未排序元素中继续寻找最小元素,并保存其下标
if (arr[min] > arr[j]) {
min = j;
}
temp = arr[min]; //将最小元素放到已排序序列的末尾
arr[min] = arr[i];
arr[i] = temp;
}
}
/**
* 并归排序
*/
//递归版
static void merge_sort_recursive(int[] result, int start, int end) {
if (start >= end)
return;
int len = end - start, mid = (len >> 1) + start;
int start1 = start, end1 = mid;
int start2 = mid + 1, end2 = end;
merge_sort_recursive(result, start1, end1);
merge_sort_recursive(result, start2, end2);
int k = start;
while (start1 <= end1 && start2 <= end2)
result[k++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++];
while (start1 <= end1)
result[k++] = arr[start1++];
while (start2 <= end2)
result[k++] = arr[start2++];
for (k = start; k <= end; k++)
arr[k] = result[k];
}
//迭代版
public static void merge_sort() {
int[] result = new int[len];
int block, start;
// 原版代码的迭代次数少了一次,没有考虑到奇数列数组的情况
for(block = 1; block < len*2; block *= 2) {
for(start = 0; start <len; start += 2 * block) {
int low = start;
int mid = (start + block) < len ? (start + block) : len;
int high = (start + 2 * block) < len ? (start + 2 * block) : len;
//两个块的起始下标及结束下标
int start1 = low, end1 = mid;
int start2 = mid, end2 = high;
//开始对两个block进行归并排序
while (start1 < end1 && start2 < end2) {
result[low++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++];
}
while(start1 < end1) {
result[low++] = arr[start1++];
}
while(start2 < end2) {
result[low++] = arr[start2++];
}
}
int[] temp = arr;
arr = result;
result = temp;
}
result = arr;
}
/**
* 快速排序
* 1.从数列中挑出一个元素,称为"基准"(pivot),
2.重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
3.递归地(recursively)把小于基准值元素的子数列和大于基准值元素的子数列排序。
*/
private static void quickSort(int start, int end) {
if (start >= end)
return;
int mid = arr[end];
int left = start, right = end - 1;
while (left < right) {
while (arr[left] <= mid && left < right)
left++;
while (arr[right] >= mid && left < right)
right--;
swap(left, right);
}
if (arr[left] >= arr[end])
swap(left, end);
else
left++;
quickSort(start, left - 1);
quickSort(left + 1, end);
}
/**
* 堆排序
* 堆排序就是把最大堆堆顶的最大数取出,将剩余的堆继续调整为最大堆,再次将堆顶的最大数取出,这个过程持续到剩余数只有一个时结束
*/
public static void heapSort(){
/*
* 第一步:将数组堆化
* beginIndex = 第一个非叶子节点。
* 从第一个非叶子节点开始即可。无需从最后一个叶子节点开始。
* 叶子节点可以看作已符合堆要求的节点,根节点就是它自己且自己以下值为最大。
*/
int len = arr.length - 1;
int beginIndex = (len - 1) >> 1;
for(int i = beginIndex; i >= 0; i--){
maxHeapify(i, len);
}
/*
* 第二步:对堆化数据排序
* 每次都是移出最顶层的根节点A[0],与最尾部节点位置调换,同时遍历长度 - 1。
* 然后从新整理被换到根节点的末尾元素,使其符合堆的特性。
* 直至未排序的堆长度为 0。
*/
for(int i = len; i > 0; i--){
swap(0, i);
maxHeapify(0, i - 1);
}
}
/**
* 调整索引为 index 处的数据,使其符合堆的特性。
* @param index 需要堆化处理的数据的索引
* @param len 未排序的堆(数组)的长度
*/
private static void maxHeapify(int index,int len){
int li = (index << 1) + 1; // 左子节点索引
int ri = li + 1; // 右子节点索引
int cMax = li; // 子节点值最大索引,默认左子节点。
if(li > len) return; // 左子节点索引超出计算范围,直接返回。
if(ri <= len && arr[ri] > arr[li]) // 先判断左右子节点,哪个较大。
cMax = ri;
if(arr[cMax] > arr[index]){
swap(cMax, index); // 如果父节点被子节点调换,
maxHeapify(cMax, len); // 则需要继续判断换下后的父节点是否符合堆的特性。
}
}
/**
*冒泡排序
* 1.比较相邻的元素。如果第一个比第二个大,就交换他们两个。
* 2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
* 3.针对所有的元素重复以上的步骤,除了最后一个。
* 4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
* 主要通过两层循环来实现。
* i=0;循环j=1,2,3,4;i=1;循环j=1,2,3;------
* 第一趟:12<34,交换位置,即12,34,54,1,5;54>34,不用交换;1<54,交换,即12,34,1,54,5;5<54,交换即12,34,1,5,54;第一趟确定了54位最大值
* 同样的套路------
*/
public static void bubblingSort() {
for (int i = 0; i<len; i++) {//循环4次
for (int j = 1; j < len-i; j++) { //循环4,3,2,1次
if (arr[j] <arr[j - 1]) {
swap(j,j-1);
}
}
}
}
/**
*插入排序
* 插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,是稳定的排序方法。
* 分析:1.假定34为有序数据,取出12,与34比较,小于--进入while,插入到该位置,k=0了,即确定12,34为有序数据;
* 2.接着取出54,与34比较,大于--不进入while,位置不变,确定12,34,54为有序数据;
* 3.取出1,与54比较,小于--进入while,插入到该位置,k--后为2,继续与12比较,小于,插入-----确定1,12,34,54为有序数据,
* ------
* 最后确定排序好的位置。
*/
public static void insertSort(){
for(int j=1;j<len;j++){
int tem=arr[j];
int k=j;
while(k>0&&tem<arr[k-1]){
arr[k]=arr[k-1];
k--;
}
arr[k]=tem;
}
}
}