排序
口诀:选堆快希不稳 选堆归基不变(排序中不稳定的 排序中与初始状态无关)
冒泡
时间:O(N^2) 空间:O(1)
思路:
- 1.一共需要的趟数,用外层for循环,长度为数组长度减1,arr.length-1
- 2.每一趟交换的次数,用内层for循环,(通过寻找规律)长度为数组长度减去次数,由于从0次开始,所以为arr.length-i-1
- 3.比较,进行交换
void bubble_sort(int arr[])
{
for(int i=0;i<arr.length-1;i++)
for(int j=0;j<arr.length-i-1;j++)//
{
if(arr[j]>arr[j+1])
{
int temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
插入
时间:O(N^2)
思路:将一个数字插入到有序表中,使用双层循环,外层循环对除了第一个元素之外的所有元素,内层循环对当前元素前面有序表进行待插入位置查找,并进行移动
public class InsertionSort {
//核心代码---开始
public static void sort(Comparable[] arr){
int n = arr.length;
for (int i = 0; i < n; i++) {
// 寻找元素 arr[i] 合适的插入位置
for( int j = i ; j > 0 ; j -- )
if( arr[j].compareTo( arr[j-1] ) < 0 )
swap( arr, j , j-1 );
else
break;
}
}
//核心代码---结束
private static void swap(Object[] arr, int i, int j) {
Object t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
}
选择
时间:O(N^2)
void selectionSort(int[] a) {
int n = a.length;
for (int i = 0; i < n; i++) {
int k = i;
// 找出最小值的小标
for (int j = i + 1; j < n; j++) {
if (a[j] < a[k]) {
k = j;
}
}
// 将最小值放到排序序列末尾
if (k > i) {
int tmp = a[i];
a[i] = a[k];
a[k] = tmp;
}
}
归并
时间:O(nlogn) 空间:O(n)
思路:划分成各个子序列进行排序 ,然后将子序列合并
void mergesort(int a[],int first,int last,int temp)//递归排序
{
if(first<last)
{
int mid=(first+last)/2;
mergesort(a,first,mid,temp);
mergesort(a,mid+1,last,temp);
mergearray(a,first,mid,last,temp);
}
}
void mergearray(int a[],int first,int mid,int last,int temp[])//合并序列
{
int i=first;
int j=mid+1;
int k=0;
while(i<=mid&&j<=last)
{
if(a[i]<=a[j])
temp[k++]=a[i++];
else
temp[k++]=a[j++];
}
while(i<=mid)
temp[k++]=a[i++];//当j>last时,序列最后的数字合并
while(j<=n)
temp[k++]=a[j++];
}
快排<分治法>
时间:O(nlogn) 空间:O(logn)
思路:随机找一个元素作为基准,将比它大的数字放在后边,比它小的数字放在前边
int Partition(int A[],int low,int high)
{
int key=A[low];
while(low<high)
{
while(low<high&&A[high]>=key)
{
--high;
}
A[low]=A[high];
while(low<high &&A[low]<=key)
{
++low;
}
A[high]=A[low];
}
A[low]=key;
return low;
}
void QuickSort(int A[],int low,int high)
{
if(low<high)
{
int middle=Partition(A,low,high);
QuickSort(A,low,middle-1);
QuickSort(A,middle+1,high);
}
}
堆排序
时间:O(nlogn) 空间:O(1)
思路:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。
private void buildMaxHeap(int[] arr, int len) {
for (int i = (int) Math.floor(len / 2); i >= 0; i--) {
heapify(arr, i, len);
}
}
private void heapify(int[] arr, int i, int len) {
int left = 2 * i + 1;
int right = 2 * i + 2;
int largest = i;
if (left < len && arr[left] > arr[largest]) {
largest = left;
}
if (right < len && arr[right] > arr[largest]) {
largest = right;
}
if (largest != i) {
swap(arr, i, largest);
heapify(arr, largest, len);
}
}
希尔
时间:O(nlogn)
void shellSort1(int* a, int n) //a:待排序数组 n:数组的长度
{
int i,j,gap;
// gap为步长,每次减为原来的一半。
for (gap = n / 2; gap > 0; gap /= 2)
{
// 共gap个组,对每一组都执行直接插入排序
for (i = 0 ;i < gap; i++)
{
for (j = i + gap; j < n; j += gap)
{
// 如果a[j] < a[j-gap],则寻找a[j]位置,并将后面数据的位置都后移。
if (a[j] < a[j - gap])
{
int tmp = a[j];
int k = j - gap;
while (k >= 0 && a[k] > tmp)
{
a[k + gap] = a[k];
k -= gap;
}
a[k + gap] = tmp;
}
}
}
}
}