// sort_test.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h"
void swap(int&a, int &b)
{
int temp = b;
b = a;
a = temp;
}
void print_arr(int* arr, int arr_len)
{
for (int i = 0; i < arr_len; i++)
{
printf("%d ", arr[i]);
}
puts("");
}
/* 【冒泡排序】
* 遍历数组中的每个元素,并比较相邻的两个元素,如果两个元素的位置不对,就将其位置调换过来。这样,在遍历了一次之后,最大/最小的元素
* 一定升到了最上面。而我们重复遍历N次,就可以将所有的元素排序号。这样每次将最大的升到最上面,就好像泡沫冒上来一样,因此叫冒泡排序。
*
* 稳定性:稳定
*
* 时间复杂度: O(n^2)
*/
void bubble_sort(int* arr, int arr_len)
{
for (int i = 0; i < arr_len - 1; i++)
{
bool sorted = true;
for (int j = 0; j < arr_len -1 - i; j++)
{
if (arr[j] > arr[j+1])
{
sorted = false;
swap(arr[j], arr[j+1]);
}
}
if (sorted)
{
break;
}
}
}
/* 【直接插入排序】
* 依次把数组的前部分看做是排序的数组,然后把后面的数组往已经排序号的部分插入。插到最后一个元素,那么整个数组就是排序号的
*
* 稳定性:稳定
*
* 时间复杂度:O(n^2)
*/
void insert_sort(int* arr, int arr_len)
{
for (int i = 1; i < arr_len; i++)
{
int val = arr[i];
int j = i - 1;
for (; j >= 0; j--)
{
if (arr[j] > val)
{
arr[j + 1] = arr[j];
}
else
{
break;
}
}
arr[j + 1] = val;
}
}
/* 【希尔排序】
* 希尔排序是在插入排序的基础上发展的来的算法。希尔排序基于插入排序的如下特征:
* 在数组基本有序的时候,算法的效率很高;在完全排序的数组下,可以达到线性的效率。
* 希尔排序又称为缩小增量插入排序: 希尔排序先取一个数值作为增量,将数组分组,再将分组中的元素按照插入排序,在依次缩小增量。当
* 增量缩小到1时,算法结束,排序完毕。
* 希尔排序增量的选择可以有很多中,其中比较常见的是希尔增量,即每次选取上个增量的一半。
*
* 稳定性:不稳定,虽然一次直接插入排序是稳定的,但是在增量不同时,不同的元素在不同的组中排序,可能会打乱其相对位置。
*
* 时间复杂度:依据增量的不同,时间复杂都也不同。时间复杂度在范围O(n*log2n) ~ O(n^2) 之间,在希尔增量下时间复杂度为O(n^2)
*/
void shell_sort(int* arr, int arr_len)
{
for (int div = arr_len / 2; div >= 1; div /= 2) // 逐渐缩小增量
{
for (int i = 0; i < div; i++) // 将数组分成div个组
{
// 对每个分组进行直接插入排序
for (int j = i + div; j < arr_len; j += div)
{
int val = arr[j];
int k = j - div;
for (; k >= 0; k -= div)
{
if (arr[k] > val)
{
arr[k + div] = arr[k];
}
else
{
break;
}
}
arr[k + div] = val;
}
}
}
}
/* 【选择排序】
* 选择排序是每次选择最大/最小的元素,放在未排序的部分的末尾或i这起始。这样,当所有的元素都进行了算则之后,就得到了一个有序的数组。
*
* 稳定性:不稳定:比如有数组{3, 3, 2},我们第一次找到最小元素2的时候,将他和第一个3交换,这样,两个3的顺序就变化了。
*
* 时间复杂度:O(n^2)
*/
void selection_sort(int *arr, int arr_len)
{
for (int i = 0; i < arr_len; i++)
{
int min_idx = i;
for (int j = i + 1; j < arr_len; j++)
{
if (arr[j] < arr[min_idx])
{
min_idx = j;
}
}
swap(arr[i], arr[min_idx]);
}
}
void quick_sort_core(int* arr, int left, int right)
{
if (left >= right)
{
return;
}
int i = left, j = right;
int key = arr[left];
while (i < j)
{
while (arr[j] >= key && j > i) { j--; }
arr[i] = arr[j];
while (arr[i] <= key && i < j) { i++; }
arr[j] = arr[i];
}
arr[i] = key;
quick_sort_core(arr, left, i - 1);
quick_sort_core(arr, i + 1, right);
}
/* 【快速排序】
* 快速排序采用了递归的思想,每次将数组分成两个部分,其中一部分一定大于某一个数,而两外一部分一定小于某一个数。
* 并采用同样的方法对两个数组递归,当递归到数组只有两个元素或者一个元素的时候,数组就有序了。
*
* 稳定性:不稳定
*
* 时间复杂度:O(nlog(n))
*/
void quick_sort(int* arr, int arr_len)
{
quick_sort_core(arr, 0, arr_len - 1);
}
int main()
{
int a[] = { 19, 45, 23, 1, 27, 123, 455, 12 };
//int a[] = { 3, 1, 2 };
int arr_len = sizeof(a) / sizeof(int);
//bubble_sort(a, arr_len);
//insert_sort(a, arr_len);
//quick_sort(a, arr_len);
//selection_sort(a, arr_len);
shell_sort(a, arr_len);
print_arr(a, arr_len);
system("pause");
return 0;
}