1.冒泡排序
基本思想:相邻位置元素两两比较,顺序相反则进行交换,每一轮会将最小或最大的元素"浮"到顶端,最终达到完全有序。
void BubbleSort(int *elem, int first, int last)
{
bool is_swap = false;
for (int i = first; i<last - 1; ++i)
{
for (int j = first; j<last - i - 1; ++j)
{
if (elem[j] > elem[j + 1])
{
Swap(&elem[j], &elem[j + 1]);
is_swap = true;
}
}
if (!is_swap)
break;
else
is_swap = false;
}
}
2.堆排序
堆排序(Heapsort)是指利用堆积树这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据,每一次调整完成后交换堆顶元素与最后一个元素形成一个新的堆,在把新的堆(不包含交换后的数据)调整为大堆/小堆。需要注意的是排升序要建大堆,排降序建小堆。
void _AdjustDown(int *elem, int first, int last, int start)
{
int n = last - first;
int i = start;
int j = 2 * i + 1;
int tmp = elem[i];
while (j < n)
{
if (j + 1<n && elem[j] < elem[j + 1])
j++;
if (tmp < elem[j])
{
elem[i] = elem[j];
i = j;
j = 2 * i + 1;
}
else
break;
}
elem[i] = tmp;
}
void HeapSort(int *elem, int first, int last)
{
//调整成大堆
int n = last - first;
int curpos = n / 2 - 1;
while (curpos >= 0)
{
_AdjustDown(elem, first, last, curpos);
curpos--;
}
//排序
int end = last - 1;
while (end > first)
{
Swap(&elem[end], &elem[first]);
end--;
_AdjustDown(elem, first, end + 1, first);
}
}
3.希尔排序
希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成个组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工作。当到达=1时,所有记录在统一组内排好序。
void ShellSort(int *elem, int first, int last)
{
int dk = last - first;
while (dk > 1)
{
dk = dk / 3 + 1;
for (int i = first; i<last - dk; ++i)
{
if (elem[i + dk] < elem[i])
{
int end = i;
int tmp = elem[end + dk];
while (end >= first && tmp<elem[end])
{
elem[end + dk] = elem[end];
end -= dk;
}
elem[end + dk] = tmp;
}
}
}
}
4.快速排序
快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。
int _Partition(int *elem, int first, int last)
{
int key = elem[first];
while (first < last)
{
while (first<last && elem[last] >= key)
last--;
elem[first] = elem[last];
while (first<last && elem[first]<key)
first++;
elem[last] = elem[first];
}
elem[first] = key;
return first;
}
void QuickSort(int *elem, int first, int last)
{
if (first >= last - 1)
return;
int pos = _Partition(elem, first, last - 1);
QuickSort(elem, first, pos); //[ )
QuickSort(elem, pos + 1, last);
}
5.归并排序
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide andConquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。 归并排序核心步骤:
void _MergeSort(int *elem, int first, int last, int *tmp)
{
if (first >= last)
return;
int mid = (first + last) / 2;
_MergeSort(elem, first, mid, tmp);
_MergeSort(elem, mid + 1, last, tmp);
//归并
int begin1, end1, begin2, end2;
begin1 = first, end1 = mid;
begin2 = mid + 1, end2 = last;
int i = first;
while (begin1 <= end1 && begin2 <= end2)
{
if (elem[begin1] < elem[begin2])
tmp[i++] = elem[begin1++];
else
tmp[i++] = elem[begin2++];
}
while (begin1 <= end1)
{
tmp[i++] = elem[begin1++];
}
while (begin2 <= end2)
{
tmp[i++] = elem[begin2++];
}
memcpy(elem + first, tmp + first, sizeof(int)*(last - first + 1));
}
void MergeSort(int *elem, int first, int last)
{
int n = last - first;
int *tmp = (int*)malloc(sizeof(int)* n);
_MergeSort(elem, first, last - 1, tmp);
free(tmp);
}
6.基数排序
基数排序属于“分配式排序”,又称“桶子法”,顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用。
//基数排序
#define K 3
#define RADIX 10
#include"list.h"
static SList list[RADIX];
//109
int _GetKey(int value, int k)
{
int key;
while(k >= 0)
{
key = value % 10; //0
value /= 10; //10
k--;
}
return key;
}
void _Distribute(int *elem, int first, int last, int k)
{
for(int i=first; i<last; ++i)
{
int key = _GetKey(elem[i], k);
SListPushBack(&list[key], elem[i]);
}
}
void _Collect(int *elem)
{
int k = 0;
for(int i=0; i<RADIX; ++i)
{
SListNode *p = list[i].head;
while(p != NULL)
{
elem[k++] = p->data;
SListPopFront(&list[i]);
p = list[i].head;
}
}
}
void RadixSort(int *elem, int first, int last)
{
for(int i=0; i<RADIX; ++i)
{
SListInit(&list[0]); //0 1 2 3 4 5 6 7 8 9
}
for(int i=0; i<K; ++i)
{
//1 分发
_Distribute(elem, first, last, i);
//2 回收
_Collect(elem);
}
}