目录
排序的概念
排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。 它分为内部排序和外部排序.
1.1直接插入排序
把待排序的记录按其关键值的大小逐个插入到一个已经排序好的有序序列中,直到所有的记录插入完为止得到一个新的有序序列.
void InsertSort(int ar[], int left, int right){
for (int i = left + 1; i < right; ++i) {
int k = left;
while (ar[i] > ar[k])
k++;
int tmp = ar[i];
for (int j = i; j > k; --j)
ar[j] = ar[j-1];
ar[k] = tmp;
}
}
总结:元素集合越接近有序,直接插入排序的算法时间效率越高,时间复杂度:O(N^2);空间复杂度O(1),它是一种稳定的排序算法.
1.2希尔排序(缩小增量法)
void ShellSort(int num[], int len)
{
int i, j, temp, step;
for (step = len / 2; step >= 1; step /= 2)//步长间隔每次减半
for (i = step; i < len; i += step)//按步长遍历数组
{
//插入排序过程
if (num[i] < num[i - step])
{
temp = num[i];
for (j = i - step; num[j] > temp; j -= step)
num[j + step] = num[j];
num[j + step] = temp;
}
}
}
希尔排序是对直接插入排序的优化,希尔排序的时间复杂度不好计算,因为增量的取值方法很多,导致很难去计算它的时间复杂度.而且希尔排序也不稳定.
1.3选择排序
每一次从待排的数据元素中选出最大(或者最小)的一个元素,存放在起始位置,直到全部待排序的数据元素排完.
int GetMinIndex(int ar[], int left, int right) {
int min_value = ar[left];
int index = left;
for (int i = left + 1; i < right; ++i) {
if (ar[i] < min_value) {
min_value = ar[i];
index = i;
}
}
return index;
}
void SelectSort(int ar[], int left, int right) {
for (int i = left; i < right - 1; ++i) {
int index = GetMinIndex(ar, i, right);
if (index != i) {
int tmp = ar[i];
ar[i] = ar[index];
ar[index] = tmp;
}
}
}
直接选择排序思考简单易理解但是效率很不好,很少在实际中使用;时间复杂度:O(N^2);空间复杂度O(1);不稳定的排序方法.
1.4堆排序
//堆排序
void _ShiftDown(int ar[], int left, int right, int start) {
int n = right - left;
int i = start;
int j = 2 * i + 1;
int tmp = ar[i];
while (j < n) {
if (j + 1 < n && ar[j] < ar[j + 1])
j++;
if (tmp < ar[j]) {
ar[i] = ar[j];
i = j;
j = 2 * i + 1;
}
else
break;
}
ar[i] = tmp;
}
void HeapSort(int ar[], int left, int right) {
int n = right - left;
int curpos = (n - 1) / 2 + left;
while (curpos >= left) {
_ShiftDown(ar, left, right, curpos);
curpos--;
}
//排序
int end = right - 1;
while (end > left) {
int tmp = ar[end];
ar[end] = ar[left];
ar[left] = tmp;
_ShiftDown(ar, left, end, left);
end--;
}
}
堆排序使用堆来选数,效率变高了.时间复杂度:O(N*logN);空间复杂度:O(1);不稳定的排序方法.
1.5冒泡排序(交换排序)
void BubbleSort_1(int ar[], int left, int right)
{
int n = right - left;
for (int i = 0; i < n - 1; ++i)
{
for (int j = 0; j < n - 1 - i; ++j)
{
if (ar[j] > ar[j + 1])
{
Swap(&ar[j], &ar[j + 1]);
}
}
}
}
1.6快速排序
//快速排序
int GetMidIndex(int ar[], int left, int right)
{
int low = left, high = right - 1;
int mid = (low + high) / 2;
if (ar[low] < ar[mid] && ar[mid] < ar[high])
return mid;
if (ar[mid] < ar[low] && ar[low] < ar[high])
return low;
return high;
}
int _Partition_3(int ar[], int left, int right)
{
//三者取中
int index = GetMidIndex(ar, left, right);
if (index != left)
Swap(&ar[left], &ar[index]);
int key = ar[left];
int pos = left;
for (int i = left+1 ; i < right; ++i)
{
if (ar[i] < key)
{
pos++;
if (pos != i)
{
Swap(&ar[pos], &ar[i]);
}
}
}
Swap(&ar[left], &ar[pos]);
return pos;
}
void InsertSort_3(int ar[], int left, int right)
{
for (int i = left; i < right; ++i)
{
int j = i;
int tmp = ar[i];
while (j > left && tmp < ar[j - 1])
{
ar[j] = ar[j - 1];
j--;
}
ar[j] = tmp;
}
}
#define M 5
void QuickSort(int ar[], int left, int right)
{
if (left >= right)
return;
if (right - left <= M)
{
InsertSort_3(ar, left, right);
}
else
{
int pos = _Partition_3(ar, left, right); //key
QuickSort(ar, left, pos);
QuickSort(ar, pos + 1, right);
}
}
1.7归并排序
//归并排序
void _MergeSort(int ar[], int left, int right, int* tmp)
{
//分解
if (left >= right)
return;
int mid = (left + right) / 2;
_MergeSort(ar, left, mid, tmp);
_MergeSort(ar, mid + 1, right, tmp);
//归并
int begin1, end1, begin2, end2;
begin1 = left, end1 = mid; //左数据
begin2 = mid + 1, end2 = right; //右数据
int k = left;
while (begin1 <= end1 && begin2 <= end2)
{
if (ar[begin1] < ar[begin2])
tmp[k++] = ar[begin1++];
else
tmp[k++] = ar[begin2++];
}
while (begin1 <= end1)
tmp[k++] = ar[begin1++];
while (begin2 <= end2)
tmp[k++] = ar[begin2++];
memcpy(ar + left, tmp + left, sizeof(int) * (right - left + 1));
}
void MergeSort(int ar[], int left, int right)
{
int n = right - left;
int* tmp = (int*)malloc(sizeof(int) * n);
_MergeSort(ar, left, right - 1, tmp);
free(tmp);
}
1.8基数排序
#include"List.h"
#define K 9
#define RADIX 10
List list[RADIX];
// k
//2 7 8
int GetKey(int value, int k)
{
int key;
while (k >= 0)
{
key = value % 10;
value /= 10;
k--;
}
return key;
}
void Distribute(int ar[], int left, int right, int k) //k代表第k次分发
{
for (int i = left; i < right; ++i)
{
int key = GetKey(ar[i], k);
ListPushBack(&list[key], ar[i]);
}
}
void Collect(int ar[])
{
int k = 0;
for (int i = 0; i < RADIX; ++i)
{
ListNode* p = list[i];
while (p != NULL)
{
ar[k++] = p->data;
p = p->next;
}
}
for (int i = 0; i < RADIX; ++i)
ListClear(&list[i]);
}
void RadixSort(int ar[], int left, int right)
{
//初始化基数
for (int i = 0; i < RADIX; ++i)
ListInit(&list[i]);
for (int i = 0; i < K; ++i)
{
//分发
Distribute(ar, left, right, i);
//回收
Collect(ar);
}
}
在数据范围集中时,效率很高;但适用范围很有限;
时间复杂度:O(MAX(N,范围))
空间复杂度;O(范围)
稳定性:稳定;