1. 快速排序
使用递归的方法。选取数组中任意一个值key作为比较(通常选取第一个值),然后数组先从后往前寻找第一个小于key的值,再从前往后寻找第一个大于key的值,交换这两个值的位置,继续前面的寻找。然后把第一个值(key)交换到两个子数组中间位置。现在两子数组,左边都小于key,右边都大于key。左右子数组再进行递归。
时间复杂度平均O(nlogn),最坏是Olog(n^2).
//快速排序
void Quick_Sort(int * arr, int left, int right) {
int i =0, j = 0, k = 0;
if (left > right) return;
k = arr[left];
i = left;
j = right;
while (i < j) {
//先从右往左找到第一个小于key的值
while (i < j && arr[j] >= k) {
j--;
}
//再从左往右找第一个大于key的值
while (i < j && arr[i] <= k){
i++;
}
//两个都找到之后交换位置
myswap(arr[i], arr[j]);
}
//然后交换第一位和左数组的最后一位
myswap(arr[left], arr[i]);
//现在左边数组都小于key,右边数组都大于key,两个子数组递归,注意:key值不要送进递归!
Quick_Sort(arr, left, i - 1);
Quick_Sort(arr, i + 1, right);
}
void myswap(int & a, int & b) {
int val = 0;
val = a;
a = b;
b = val;
}
2. 归并排序
需要一个辅助数组来存储局部交换之后的值,然后将辅助数组赋给原数组。时间复杂度是O(nlogn)不变。
//归并排序,vector操作,引用传递参数
void Merge_Sort(vector<int> & data) {
if (data.size() == 0) return;
int length = data.size();
vector<int> copy(length, 0);//初始化与data同样大小的copy,全是0
//for (int i = 0; i < length; i++){
// copy.push_back(data[i]);
//}
MergeSortCore(data, copy, 0, length - 1);
}
void MergeSortCore(vector<int> & data, vector<int> & copy, int start, int end) {
if (start == end) {
copy[start] = data[start]; //每一个数组值都会递归到这个地方,相当于将data数组赋值给copy数组。//拷贝初始化之后这个去掉也没事
return;
}
int length = (end - start) / 2;//将数组拆成两部分
//计算左右两部分中逆序数
MergeSortCore(data, copy, start, start + length);
MergeSortCore(data, copy, start + length + 1, end);
int i = start + length; //分别从两个子数组的最末端开始,同时辅助数组copy也从两个相邻子数组的末端开始
int j = end;
int index = end;
while (i >= start && j >= start + length + 1) {
if (data[i] > data[j]) {
copy[index--] = data[i--];//将大数放在末尾,相当于小到大排序
}
else copy[index--] = data[j--];
}
//有可能某一个子数组还有值,而另一个已经遍历完了,就把剩下的接着顺序复制到copy中子数组.
for (; i >= start; i--) {
copy[index--] = data[i];
}
for (; j >= start + length + 1; j--) {
copy[index--] = data[j];
}
//更新原data数组,很重要
for (int i = start; i <= end; i++) {
data[i] = copy[i];
}
}
3. 选择排序
思想:选数组第一个位置为最小值的位置,然后遍历后面数组zha找出实际最小值的位置,和第一个位置的值交换。然后选择数组第二个位置开始重复。
//选择排序
void Choose_Sort(int * arr, int length)
{
int min;
int temp;
for (int i = 0; i < length-1; i++)
{
min = i;
for (int j = i+1; j < length; j++)
{
if (arr[j] < arr[min])
{
min = j;
}
}
if (i != min)
{
temp = arr[i];
arr[i] = arr[min];
arr[min] = temp;
}
}
}
4. 冒泡排序
比较相邻位置的数字,较大的值不断的往后面放。
void Bubble_Sort(int * arr, int length)
{
int temp;
for (int i = 0; i < length-1; i++) //此循环记录第几遍冒泡交换
{
for (int j = 0; j < length-i-1; j++)
{
if (arr[j] > arr[j+1])
{
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
5. 堆排序
时间复杂度O(nlogn),不稳定排序。
参考:http://www.cnblogs.com/skywang12345/p/3602162.html
void maxheap_down(int a[], int start, int end)
{
int c = start; // 当前(current)节点的位置
int l = 2 * c + 1; // 左(left)孩子的位置
int tmp = a[c]; // 当前(current)节点的大小
for (; l <= end; c = l, l = 2 * l + 1)
{
// "l"是左孩子,"l+1"是右孩子
if (l < end && a[l] < a[l + 1])
l++; // 如果有左右两孩子中选择较大者,即m_heap[l+1]
if (tmp >= a[l])
break; // 调整结束
else // 交换值
{
a[c] = a[l];
a[l] = tmp;
}
}
}
/*
* 堆排序(从小到大)
*
* 参数说明:
* a -- 待排序的数组
* n -- 数组的长度
*/
void heap_sort_asc(int a[], int n)
{
int i;
// 从(n/2-1) --> 0逐次遍历非叶节点。遍历之后,得到的数组实际上是一个(最大)二叉堆。
for (i = n / 2 - 1; i >= 0; i--)
maxheap_down(a, i, n - 1);
// 从最后一个元素开始对序列进行调整(将上面找到的堆顶最大值放在尾部)
// 不断的缩小调整的范围直到第一个元素
for (i = n - 1; i > 0; i--)
{
// 交换a[0]和a[i]。交换后,a[i]是a[0...i]中最大的。
swap(a[0], a[i]);
// 调整a[0...i-1],使得a[0...i-1]仍然是一个最大堆。
// 即,保证a[i-1]是a[0...i-1]中的最大值。
maxheap_down(a, 0, i - 1);
}
}