近来复习排序算法和查找算法,做个总结,巩固一下。
1.直接插入排序: 拓展并维护有序区,直至全部有序
code:
void insertSort(int a[], size_t arrSize)
{
size_t i, j;
for(i = 1; i <= arrSize-1; ++i)
{
j = i;
a[0] = a[j+1];
while(j>0)
{
if(a[0]<a[j])
{
a[j+1] = a[j];
--j;
}
else break;
}
a[j+1] = a[0];
}
}
复杂度:O(n^2)
稳定性:是
最好情况:O(n)顺序排
最差情况:O(n^2)逆序排
2.希尔排序: 取整数d1<n,将相隔d1的整数放在一组进行直接插入排序;再取d2<d1,重复上述操作;直至di=1,所有数放在一组中排序
code:
void shellSort(int a[], int arrSize)
{
int d, i, j;
for (d = (arrSize+1)/2; d >= 1; d = (d+1)/2) //保证以di = 1结束
{
for (i = d; i < arrSize; ++i)
{
int tmp = a[i];
for (j = i - d; j >= 0 && (a[j] > tmp); j -= d)
{
a[j+d] = a[j];
}
a[j+d] = tmp;
}
if (d == 1) break;
}
}
复杂度:O(n^2) 比直接插入排序好些
稳定性:是
3.冒泡排序: 从后往前将相邻两个元素中优先级较高的往前“冒”。
code:
void exchange(int &x, int &y)
{
int tmp = x;
x = y;
y= tmp;
}
void bubbleSort(int a[], size_t arrSize)
{
for (size_t i = 0; i < arrSize-1; ++i)
{
for (size_t j = arrSize-1; j > i; --j)
{
if(a[j] < a[j-1])
exchange(a[j], a[j-1]);
}
}
}
复杂度:O(n^2)
稳定性:是
最好情况:O(n)顺序排
最差情况:O(n^2)逆序排
4.快速选择排序: 分治+递归,先选一个基准Pivot,一般是第一个或是最后一个,遍历一趟将元素分为左右两部分,以升序举例,左半部分比Pivot小,右半部分比Pivot大。这样继续对左右两边分治下去,可得有序序列。code:
void swap(int &x, int &y)
{
int t = x;
x = y;
y = t;
}
int Partitioin(int arr[], int p, int q)//arr[p]~arr[q]
{
int ele = arr[q];
int i = p-1;
for (int j = p; j <= q - 1; ++j)
{
if (arr[j] <= ele)
{
++i;
swap(arr[i], arr[j]);
}
}
swap(arr[i+1], arr[q]);
return i+1;
}
void QuickSort(int arr[], int p, int q)//arr[p]~arr[q]
{
if (p < q)
{
int pivot = Partitioin(arr, p, q);
QuickSort(arr, p, pivot-1);
QuickSort(arr, pivot+1, q);
}
}
复杂度:O(nlogn)
稳定性:是
最差情况:O(n^2)数组已经排好序
5.直接选择排序: 每趟遍历未排好序的数,将优先级高的交换到前面来
void selectSort(int a[], size_t arrSize)
{
size_t i, j;
for (i = 0; i < arrSize; ++i)
{
size_t tmp = i;
for(j = i+1; j < arrSize; ++j)
{
if(a[j] < a[tmp])
tmp = j;
}
if(i != tmp)
{
int tval = a[i];
a[i] = a[tmp];
a[tmp] = tval;
}
}
}
复杂度:O(n^2)
稳定性:是
最好情况:O(n)顺序排
最差情况:O(n^2)逆序排
6.堆排: 构造堆,以最小堆为例,堆顶元素比左右孩子都小。关键是堆的构建和维护。
code:
void sink(int heap[], int heapSize, int p)
{
int q = p << 1, tmp = heap[p];
while(q <= heapSize)
{
if(q < heapSize && heap[q+1] < heap[q])
q++;
if(heap[q] >= tmp)
break;
heap[p] = heap[q];
p = q;
q = p << 1;
}
heap[p] = tmp;
}
void build(int heap[], int heapSize)
{
int i;
for (i = heapSize/2; i >= 1; --i)
sink(heap, heapSize, i);
}
void insert(int heap[], int heapSize, int val)
{
heap[++heapSize] = val;
int q = heapSize, p = heapSize >> 1;
while(p && heap[p] > val)
{
heap[q] = heap[p];
q = p;
p = q >> 1;
}
heap[q] = val;
}
int del(int heap[], int heapSize)
{
int val = heap[1];
heap[1] = heap[heapSize--];
sink(heap, heapSize, 1);
return val;
}
void heapSort(int heap[], int heapSize, int Sorted[])
{
int i, SortedSize;
for (i = 1, SortedSize = heapSize; i <= SortedSize; ++i)
{
Sorted[i] = del(heap, heapSize);
heapSize--;
}
}
复杂度:O(nlogn)
稳定性:是
最好情况:O(n)顺序排
最差情况:O(nlogn)逆序排
7.归并排序: 将n个元素分成各含n/2个元素的子序列,用合并排序对子序列递归排序,合并已排序的序列。
code:
#define INF 2147483647
int a[] = {2,1,4,5,9,6,7,3,8};
int L[100], R[100];
void merge(int a[], int p, int q, int r) //Merge array between a[p~q] and a[q+1~r]
{
int n1 = q - p + 1, n2 = r - q, i , j, k;
for (i = 1; i <= n1; ++i)
L[i] = a[p+i-1];
for (i = 1; i <= n2; ++i)
R[i] = a[q+i];
L[n1+1] = INF; R[n2+1] = INF;
for (i= 1, j = 1,k = p; k <= r; ++k)
{
if (L[i] <= R[j])
a[k] = L[i++];//原地,不保留原数组
else
a[k] = R[j++];
}
}
void mergeSort(int a[], int p, int r)
{
if (p < r)
{
int q = (p+r) / 2;
mergeSort(a, p, q);
mergeSort(a, q+1, r);
merge(a, p, q, r);
}
}
复杂度:O(nlogn)
稳定性:是
最好情况:O(n)顺序排
最差情况:O(nlogn)逆序排
8.基数排序 : 对十进制数来说,每位有10种情况,一次查看一位,按数字位排序。
code:
int base[] = {0, 1, 10, 100, 1000, 10000, 100000, 1000000, 1000000};
multimap<int, int> m_map;
void handleSort(int a[], int arrSize, int d)
{
m_map.clear();
for (int i = 0; i < arrSize; ++i)
{
m_map.insert(make_pair(a[i]%base[d+1]/base[d], a[i]));
}
int p = 0;
for (int i = 0; i <= 9; ++i)
{
multimap<int, int>::size_type cnt = m_map.count(i);
multimap<int, int>::iterator itr = m_map.find(i);
for (multimap<int, int>::size_type ct = 0; ct != cnt; ++ct, ++itr)
a[p++] = itr->second;
}
}
void radixSort(int a[], int arrSize, int d)//d represents the digits of a[x]
{
for (int i = 1; i <= d; ++i)
handleSort(a, arrSize, i);
}
复杂度:O(n)
稳定性:是