排序模版:
public static bool less(int a,int b)
{
return a - b < 0;
}
public static void exch(int[] a,int i,int j)
{
int t = a[i];
a[i] = a[j];
a[j] = t;
}
(1)冒泡排序
int[] arr = { 2, 3, 4, 67, 23, 99, 1 };
冒泡排序 n^2,稳定的排序算法 bubble sort
for (int j = 0; j <= arr.Length - 1; j++)
{
for (int i = 0; i < arr.Length - 1 - j; i++)
{
if (arr[i] > arr[i + 1])
{
int temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
}
}
}
插入排序,希尔排序是其的改良版 n^2,稳定排序
public int[] Insertion(int[] a)
{
int length = a.Length;
for(int i = 1; i < length; i++)
{
for(int j = i; j > 0 && less(a[j], a[j - 1]); j--)
{
exch(a, j, j - 1);
}
}
return a;
}
(3)选择排序
选择排序 n^2 不是稳定排序
public int[] Selection(int[] a)
{
int length = a.Length;
for(int i = 0; i < length; i++)
{
int min = i;
for(int j = i+1; j<a.Length;j++)
{
if (less(a[j], a[min]))
min = j;
}
exch(a, i, min);
}
return a;
}
ps:分的间隔算法可以不一样
希尔排序 nlog2n 稳定排序
public int[] shell(int[] a)
{
int length = a.Length;
int h = 1;
while (h<length/3) h = 3 * h + 1;//分好间隔
while (h >= 1)//一直逆推,让间隔=1
{
for (int i = h; i < length; i++)
{
for (int j = i; j >= h && less(a[j], a[j - h]); j -= h)
{
exch(a, j, j - h);
}
}
h = h / 3;
}
return a;
}
(5)快速排序
快速排序:空间1,时间nlogn,是一种不稳定的排序算法
private static void QuickSort(int[] arr,int begin,int end){
if(begin>=end) return;
int pivotIndex=QuickSort_Once(arr,begin,end);
QuickSort(arr,begin,pivotIndex-1);
QuickSort(arr,pivotIndex+1,end);
}
private static int QuickSort_Once(int[] arr,int begin,int end){
int pivot=arr[begin];
int i=begin;
int j=end;
while(i<j){
while(arr[j]>=pivot&&i<j)
j--;
arr[i]=arr[j];
while(arr[i]<=pivot&&i<j)
i++;
arr[j]=arr[i];
}
arr[i]=pivot;
return i;
}
}
(6)折半查找,二分查找,时间复杂度logn。
条件:一定要有序。
public int Search_Bin(int[] arr,int key)
{
int low=0;
int high=arr.length-1;
while(low<=high){
int mid=(low+high)/2
if(arr[mid]==key) return mid;
else if(key<arr[mid])
high=mid-1;
else if(key>arr[mid])
low=mid+1;
}
return 0;
}
(7)堆排序
时间复杂度:nlogn
不稳定排序
///
/// 对i节点做一次heapify
///
/// 数组
/// 数组长度
/// 从哪个节点开始
///
int[] heapify(int[] tree,int n,int i)
{
if (i >= n)
return null;
//首先计算出i序号的子节点的序号
int c1 = 2 * i + 1;
int c2 = 2 * i + 2;
int max = i;
//i与两个子节点对比,找出最大的那个
if (c1 < n && tree[c1] > tree[max])
{
max = c1;
}
if (c2 < n && tree[c2] > tree[max])
{
max = c2;
}
//如果i为最大,就不交换,否则要和最大的那个子节点交换值
//值交换后,再对i下面的节点也做次heapify,递归出口是i
if (max != i)
{
exch(tree, max, i);
heapify(tree, n, max);
}
return tree;
}
///
/// 找到最后一个节点的父节点,然后父节点依次往上都做依次heapify操作
/// 就能构建出一个堆
///
/// 数组
/// 数组的长度
///
int[] build_heap(int[] tree,int n)
{
//找到最后一个节点
int last_node = n - 1;
//找到最后一个节点的父节点
int parent = (last_node - 1) / 2;
//依次从父节点往上做heapify
for(int i = parent; i >= 0; i--)
{
heapify(tree, n, i);
}
return tree;
}
///
/// 堆排序
///
/// 要排序的数组
/// 数组长度
///
int[] heapsort(int[] tree,int n)
{
//构建一个堆,这个堆的1个节点肯定是最大的那个
build_heap(tree, n);
//把最大的节点依次和第0个交换,每一次都是从第一节点做heapify
for(int i = n - 1; i >= 0; i--)
{
exch(tree, 0, i);
heapify(tree, i, 0);
}
return tree;
}
void exch(int[] arr,int i,int j)
{
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
///
/// 归并排序的总入口
///
///
///
void merge_sort(int[] arr,int n)
{
int[] tempArr = new int[n];
msort(arr, tempArr, 0, n - 1);
}
///
/// 归并排序
///
/// 数组
/// 临时存储的排好了序的数组
/// 指向数组的左边,即开头
/// 指向数组的右边,即结尾
void msort(int[] arr,int[] tempArr,int left,int right)
{
if (left < right)//一直到只有一个元素时停止划分
{
//找中间点划分
int mid = (left + right) / 2;
//递归划分左半区域
msort(arr, tempArr, left, mid);
//递归划分右半区域
msort(arr, tempArr, mid + 1, right);
//合并已经排序的部分
merge(arr, tempArr, left, mid, right);
}
}
///
/// 合并排序
///
/// 要排序的数组
/// 临时存储的数组
/// 要排序的左半部分
/// 中间点
/// 要排序的右半部分
void merge(int[] arr,int[] tempArr,int left,int mid,int right)
{
//标记左半区的第一个未排序元素
int l_pos = left;
//标记右半区第一个未排序元素
int r_pos = mid + 1;
//临时数组的元素下标
int pos = left;
//合并
while (l_pos <= mid && r_pos <= right)
{
//如果左半区第一个元素更小就把左半区第一个元素放入
//临时的数组中,如果右半区的更小,就放入右半区的第一个元素
//然后更小的那个半区的指针l_pos往后挪
if (arr[l_pos] < arr[r_pos])
{
tempArr[pos] = arr[l_pos];
pos++;
l_pos++;
}
else
{
tempArr[pos] = arr[r_pos];
pos++;
r_pos++;
}
}
//如果左半区还有剩
while (l_pos <= mid)
{
tempArr[pos] = arr[l_pos];
pos++;
l_pos++;
}
//如果右半区还有剩
while (r_pos <= right)
{
tempArr[pos] = arr[r_pos];
pos++;
r_pos++;
}
//把临时数组拷贝到之前的数组
while (left <= right)
{
arr[left] = tempArr[left];
left++;
}
}