排序的几种方法
1.冒泡 选择 插入三种排序方法
/**
* 描述:
* 冒泡、选择、插入三种排序
*/
public class Sort {
@Test
public void test01(){
int[] arr = new int[]{12,5,7,89,54,32,13};
// 在一个无序的数组中,按顺序搜索数组找元素,时间复杂度:O(n)
for (int i = 0; i < arr.length; i++) {
if(arr[i] == 54)
{
System.out.println("find 54!");
break;
}
}
insertSort(arr);
// [5, 7, 12, 13, 32, 54, 89]
int idx = binarySearch(arr, 0, arr.length-1, 54);
System.out.println("54 idx:" + idx);
}
/**
* 二分查找的实现,找到val返回其下标,找不到返回-1
* 时间复杂度:O(log2n) 对数时间
* @param arr
* @param first
* @param last
* @param val
* @return
*/
private int binarySearch(int[] arr, int first,
int last, int val) {
while(first <= last){
int mid = (first + last)/2;
if(val < arr[mid]){
last = mid-1;
} else if(val > arr[mid]){
first = mid+1;
} else {
return mid;
}
}
return -1;
}
public static void main(String[] args) {
int[] arr = new int[]{12,5,7,89,54,32,13};
/*int[] arr = new int[10000];
Random rd = new Random();
for (int i = 0; i < arr.length; i++) {
arr[i] = rd.nextInt(65535);
}*/
long begin, end;
// 冒泡排序
begin = System.currentTimeMillis();
//bubbleSort(arr);
end = System.currentTimeMillis();
System.out.println("bubbleSort:" + (end-begin) + "ms");
// 选择排序
begin = System.currentTimeMillis();
//choiceSort(arr);
end = System.currentTimeMillis();
System.out.println("choiceSort:" + (end-begin) + "ms");
//System.out.println(Arrays.toString(arr));
// 插入排序
begin = System.currentTimeMillis();
insertSort(arr);
end = System.currentTimeMillis();
System.out.println("insertSort:" + (end-begin) + "ms");
System.out.println(Arrays.toString(arr));
}
/**
* 插入排序的思想
* 4 8 12 67 90
* k
* 20 32 41 28
* j i
* 插入排序的优化
* @param arr
*/
private static void insertSort(int[] arr) {
// 12 12 7 8 9
for(int i=1; i<arr.length; ++i) {
int val = arr[i];
// 优化成二分查找合适的插入位置,不再使用线性查找
// 0 j 找第一个小于val的值
int index = findInsertPos(arr, 0, i-1, val);
for(int j=i; j>index; --j){
arr[j] = arr[j-1];
}
arr[index] = val;
/*
// 在i前面已经排序好的序列中,找i元素插入的合适的位置
int j=i-1;
for(; j>=0; --j){
if(val < arr[j]) {
arr[j+1] = arr[j];
}
else {
break;
}
}
// 把val元素插入到当前位置,然后循环结束
arr[j+1] = val;
*/
}
}
private static int findInsertPos(
int[] arr, int i, int j, int val) {
while(i <= j)
{
int mid = (i+j)/2;
if(val < arr[mid])
{
j = mid-1;
} else {
i = mid+1;
}
}
return i;
}
/**
* 选择排序
* 12 4 67 8 90 32 41 46
* 1. 当前元素和后面元素比较,找出最小值
* 2.
* 不稳定
* 2 3 5 5
* @param arr
*/
private static void choiceSort(int[] arr) {
for(int i=0; i<arr.length-1; ++i)
{
int min = arr[i];
int k = i;
for(int j=i+1; j<arr.length; ++j)
{
if(min > arr[j]){
min = arr[j];
k = j;
}
}
// 0 k
if(k != i)
{
int tmp = arr[i];
arr[i] = arr[k];
arr[k] = tmp;
}
}
}
/**
* 冒泡排序
* 排序算法的两个问题:
* 1.时间复杂度:O(n^2) 空间复杂度:O(1)
* 2.稳定性:稳定
* @param arr
*/
private static void bubbleSort(int[] arr) {
for(int i=0; i<arr.length-1; ++i){
boolean swap = false;
for(int j=0; j< arr.length-1-i; ++j){
if(arr[j] > arr[j+1]){
swap = true;
int tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
if(!swap){
return;
}
}
}
}
2.堆排
/**
* 描述: 堆排序
*/
public class HeapSort {
public static void main(String[] args) {
int[] arr = new int[10];
Random rd = new Random();
for (int i = 0; i < arr.length; i++) {
arr[i] = rd.nextInt(100);
}
heapSort(arr);
System.out.println(Arrays.toString(arr));
}
/**
* 实现堆排序
* @param arr
*/
private static void heapSort(int[] arr) {
int n = arr.length-1;
// 从第一个非叶子节点开始,把大值往父节点调整
for(int i=(n-1)/2; i>=0; --i){
adjust(arr, i, arr.length);
}
for(int i=n; i>=0; --i){
//0 <=> i 它们的值进行交换
int tmp = arr[0];
arr[0] = arr[i];
arr[i] = tmp;
//再继续进行堆的调整 adjust
adjust(arr, 0, i);
}
}
/**
* 堆的调整函数,把每一个节点,和其左右孩子节点的最大值放到当前节点处
* @param arr
* @param i
* @param length
*/
private static void adjust(int[] arr, int i, int length) {
int val = arr[i];
for(int j=2*i+1; j<length; j=2*j+1){
// 先用j标识值最大的孩子
if(j+1 < length && arr[j+1] > arr[j]){
j++;
}
if(arr[j] > val){
arr[i] = arr[j];
i = j;
} else {
break;
}
}
arr[i] = val;
}
}
3.归并排序
/**
*
* 描述: 归并排序 - 外部排序
*/
public class MergeSort {
public static void main(String[] args) {
int[] arr = new int[20];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int)(Math.random()*100);
}
mergeSort(arr, 0, arr.length-1);
System.out.println(Arrays.toString(arr));
}
/**
* 实现归并排序
* @param arr
* @param i
* @param j
*/
private static void mergeSort(int[] arr, int i, int j) {
if(i < j)
{
int mid = (i+j)/2;
/**
* 以下的操作,先进行数组划分,直到划分为单个元素以后,逐级向上回溯
* 的时候,进行合并操作
*/
mergeSort(arr, i, mid);
mergeSort(arr, mid+1, j);
merge(arr, i, j); // 合并两个有序的序列
}
}
/**
* 合并两个有序的序列
* @param arr
* @param low
* @param high
*/
private static void merge(int[] arr, int low, int high) {
int[] tmp = new int[high-low+1];
int mid = (low+high)/2; // i-mid mid+1-j
int i=low; // [i, mid]
int j=mid+1; // [mid+1, high]
int idx=0;
// 3 12 5 8
while(i <= mid && j <= high){
if(arr[i] > arr[j]){
tmp[idx++] = arr[j++];
} else {
tmp[idx++] = arr[i++];
}
}
while(i <= mid){ //
tmp[idx++] = arr[i++];
}
while(j <= high){
tmp[idx++] = arr[j++];
}
// 把tmp里面合并的有序段再写回arr的[low,high]
for(int k=low; k<=high; ++k){
arr[k] = tmp[k-low];
}
}
}