归并排序
将待排序的元素序列分成两个长度相等的子序列,对每一个子序列排序,然后将他们合并成一个序列。
划分
归并
void mergesort(int* a, int begin, int end, int* tmp)//归并排序
{
assert(a);
if (begin >= end)
{
return;
}
int mid = begin +((end - begin) >> 1);
mergesort(a, begin, mid, tmp);
mergesort(a, mid + 1, end, tmp);
mergesort(a, begin, mid, mid + 1, end, tmp);
}
时间复杂度:最优情况:O(NlgN)
最差情况:O(NlgN)
空间复杂度:O(N),是一种稳定的算法
选择排序
从n个数中选择一个最小的数放到数组的第一个位置上,在从剩下n-1个数中选出最小数,放到开头,依次进行下去,知道剩下最后一个元素即为最大数,放到最后位置。
void swap(int* x, int* y)
{
int tmp = *x;
*x = *y;
*y = tmp;
}
void selectsort(int* a, int n)//选择排序
{
assert(a);
int begin = 0;
int end = n - 1;
while (begin <= end)
{
int min = begin;
int max = begin;
for (int i = begin; i <= end; i++)
{
if (a[i] > a[max])
max = i;
if (a[i] < a[min])
min = i;
}
swap(&a[begin], &a[min]);
swap(&a[end], &a[max]);
++begin;
--end;
}
}
时间复杂度:最优情况:O(n^2)
最差情况:O(n^2)
空间复杂度:O(1),是一种不稳定的算法
快速排序
任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置为止。
void swap(int* x, int* y)
{
int tmp = *x;
*x = *y;
*y = tmp;
}
int quicksort(int* a, int begin, int end,int n)//快速排序
{
assert(a);
int key = a[end];
int keyindex = 0;
begin = 0;
end = n - 1;
while (begin < end)
{
while (begin < end&&a[begin] <= key)
++begin;
while (begin < end&&a[begin] >= key)
--end;
swap(&a[begin], &a[end]);
}
swap(&a[begin], &a[end]);
return begin;
}
时间复杂度:最优情况:O(nlgn)
最差情况:O(n^2)
空间复杂度:O(lgn),是一种不稳定的算法
插入排序
基本思想:
每一步将一个待排序的元素,按其排序码的大小,插入到前面已经排好序的一组元素的合适位置上,直到元素全部插完为止。
void insertsort(int* a,int n)//插入排序
{
assert(a);
int i = 0;
for (i = 0; i < n-1; i++)
{
int end = i;
int tmp = a[end + 1];
while (end >= 0 && a[end] > tmp)
{
a[end + 1] = a[end];
--end;
}
a[end + 1] = tmp;
}
}
时间复杂度:最优情况:O(n)
最差情况:O(n^2)
空间复杂度:O(1),是一种稳定的算法
堆排序
堆排序就是把最大堆堆顶的最大数取出,将剩余的堆继续调整为最大堆,再次将堆顶的最大数取出,这个过程持续到剩余数只有一个时结束。在堆中定义以下几种操作:
- 最大堆调整(Max-Heapify):将堆的末端子节点作调整,使得子节点永远小于父节点
- 创建最大堆(Build-Max-Heap):将堆所有数据重新排序,使其成为最大堆
- 堆排序(Heap-Sort):移除位在第一个数据的根节点,并做最大堆调整的递归运算
继续进行下面的讨论前,需要注意的一个问题是:数组都是 Zero-Based,这就意味着我们的堆数据结构模型要发生改变
/**
* 从 index 开始检查并保持最大堆性质
*
* @array
*
* @index 检查的起始下标
*
* @heapSize 堆大小
*
**/
function maxHeapify(array, index, heapSize) {
var iMax = index,
iLeft = 2 * index + 1,
iRight = 2 * (index + 1);
if (iLeft < heapSize && array[index] < array[iLeft]) {
iMax = iLeft;
}
if (iRight < heapSize && array[iMax] < array[iRight]) {
iMax = iRight;
}
if (iMax != index) {
swap(array, iMax, index);
maxHeapify(array, iMax, heapSize); // 递归调整
}
}
function swap(array, i, j) {
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
时间复杂度:最优情况:O(nlgn)
最差情况:O(nlgn)
空间复杂度:O(1),是一种不稳定的算法
希尔排序
是插入排序的一种优化
时间复杂度:最优情况:O(n)
最差情况:O(n^2)
空间复杂度:O(1),是一种不稳定的算法
void xiersort(int* a, int n)//希尔排序
{
assert(a);
int gap = 3;
int i = 0;
while (gap > 0)
{
gap = gap / 2;
for (i = 0; i <n - gap; i++)
{
int end = i;
int tmp = a[end + 1];
while (end >= 0 && a[end] > tmp)
{
a[end + gap] = a[end];
--end;
}
a[end + gap] = tmp;
}
}
}
冒泡排序
相邻元素进行比较,第一趟完,就把最大的放到数组的最后位置,在比较剩下的n-1个元素,把这n-1个数中最大数放到倒数第二的位置,依次进行,直到剩最后一个元素,就是最小的元素。
时间复杂度:最优情况:O(n)
最差情况:O(n^2)
空间复杂度:O(1),是一种稳定的算法
void maopaosort(int* a, int n)//冒泡排序
{
assert(a);
int i = 0;
int j = 0;
for (i = 0; i < n; i++)
{
for (j = 0; j < n - 1 - i; j++)
{
if (a[j] > a[j + 1])
{
int tmp = a[j];
a[j] = a[j + 1];
a[j + 1] = tmp;
}
}
}
}