排序算法
选择排序算法
直接选择排序、堆排序
交换排序
冒泡排序、快速排序
插入排序
直接插入排序、折半插入排序、Shell排序
归并排序
桶式排序
基数排序
冒泡排序 O(n^2)
从第一个元素开始,比较两个相邻的元素。若相邻的元素的相对位置不正确,则交换位置;否则比较后面两个相邻的元素。
八个元素最多需要七轮排序。
核心代码:
int[] bubble(int[] array){
for(int i = 0;i < array.length - 1;i++){
//n个元素共比较n-1轮
for(int j = 0;j < array.length - i - 1;j++){//j和相邻元素j+1比较,length-1不然会越界
//每轮比较剩下的元素,n个元素比较n-1次完成一轮
if(array[j] > array[j+1]){
int temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
return array;
}
选择排序 O(n^2)
int[] select(int[] array){
for(int i = 0;i < array.length - 1;i++){
int min = i;
for(int j = i + 1;j < array.length;j++){//j依次向后直到最后一个元素
if(array[j] < array[min])
min = j;
}
int temp = array[i];
array[i] = array[min];
array[min] = temp;
}
return array;
}
插入排序 O(n^2)
int[] insertion(int[] array){
for(int i = 0;i < array.length - 1;i++){//控制比较的轮数和已经排好序的元素
int j = i + 1;//已经排好序元素外的第一个元素
while(j > 0 && array[j] < array[j-1]){//新元素一步一步往里换位置
int temp = array[j];
array[j] = array[j-1];
array[j-1] = temp;
j = j - 1;
}
}
return array;
}
归并排序 O(n*logn)
public static void mergeSort(int[] array, int low, int high){
//将数组拆开
int mid = (low + high) / 2;
if(low < high){//设置递归结束条件
//左边
mergeSort(array, low, mid);
//右边
mergeSort(array, mid+1, high);
//归并
merge(array, low, mid, high);
System.out.println(Arrays.toString(array));
}
}
public static void merge(int[] array, int low, int mid, int high){
//将数组依次比较合并
int[] temp = new int[high - low + 1];//实例化一个临时数组来排序
int i = low;
int j = mid + 1;
int k = 0;
//循环 依次把较小的数先放进数组
while(i <= mid && j <= high){
if(array[i] < array[j])
temp[k++] = array[i++];
else
temp[k++] = array[j++];
}
//若比较完左面还剩数组,把左面依次放进temp
while(i <= mid){
temp[k++] = array[i++];
}
//若比较完右边还剩数组,把右边依次放进temp
while(j <= high){
temp[k++] = array[j++];
}
//排好序的数组放回
for(int n = 0; n < temp.length; n++){
array[n + low] = temp[n];
}
}
快速排序 O(n*logn)
定义3个指针(high, low, pivot),要求low指向的元素小于等于pivot指向的元素;high指向的元素大于等于pivot指向的元素。
首先,指向high的指针先向左移动(依次比较),若遇到比pivot指向的元素小的元素停下。
将high指向的元素和low指向的元素(此时low和pivot指向同一元素)换位置。
然后low开始向右移动(依次比较),若遇到比pivot指向的元素大的元素停下。
将high指向的元素和low指向的元素换位置。
然后,high再向左移动,找到比low指向元素小的元素停下。
同理,将low指向的元素和high指向的元素换位置。
至此,第一轮排序结束。23(pivot元素)左边都是比它小的元素,右边都是比它大的元素。然后以pivot指向的元素为分界线,再对左右两边的小数组进行上述操作。
代码实现:
public static void quickSort(int[] array, int low, int high){
if(low < high){
int i = low;
int j = high;
int pivot = array[i];
while(i < j){//控制左右指针轮流向中间聚拢
//右指针先向左移动,遇到比pivot小的停下
while(i<j && array[j]>pivot)
j--;
if(i < j)
array[i++] = array[j];//把第j个元素的值给第i个元素
//左指针向右移动,遇到比pivot大的停下
while(i<j && array[i]<pivot)
i++;
if(i < j)
array[j--] = array[i];//把第i个元素的值给了第j个元素
}
array[i] = pivot;//把pivot的值再换给第i个元素(重复)
quickSort(array, low, i-1);//pivot前看作一个小数组
quickSort(array, i+1, high);//pivot后看作一个小数组
}
}
堆排序 O(n*logn)
public static void heapSort(int[] array){
//构建大根堆,从最后一个不是叶子结点的节点开始
for(int i = array.length / 2 - 1; i >= 0; i--){
// array.length / 2 - 1 是最后一个不是叶子节点的节点,从这个节点开始遍历到根节点找最大值
maxHeapDown(array, i, array.length - 1);
}
//从数组最后一个节点依次和根节点互换位置,然后排序
for(int i = array.length - 1; i > 0; i--){
int temp = array[i];
array[i] = array[0];
array[0] = temp;
maxHeapDown(array, 0, i - 1);
}
}
public static void maxHeapDown(int[] array, int start, int end){//start 当前节点起始位置 end 数组末尾
for(int child = 2 * start + 1; child <= end; child = 2 * child + 1){//child 左孩子节点
if(child<end && array[child]<array[child+1])
//确保存在左右自节点,选择较大的一个
child++;
if(array[child] > array[start]) {
int temp = array[child];
array[child] = array[start];
array[start] = temp;
}
else
break;
start = child;
}
}