目录
*****
因此有:
稳不稳定看相同元素排序前后的相对位置有没有改变
初始数据集的排列顺序对算法的性能无影响的有: 堆排序,归并排序,选择排序(最好最坏一样)
待排序数据已有序时,花费时间反而最多的是:快排
只有少量数据(5~25个)时,花费时间最少的时:直接插入排序
此表都要记牢
*****
直接插入排序
//直接插入排序
void InsertSort(int* a, int n) {
for (int i = 1; i < n;i++) {
int tmp = a[i];
int j = i - 1;
for (; a[j] > tmp && j >= 0; j--) {
a[j + 1] = a[j];
}
a[j+1] = tmp;
}
}
折半排序
//折半排序
void BTInsertSort(int* a, int n) {
for (int i = 1; i < n; i++) {
int tmp = a[i];
int first = 0;
int final = i - 1;
int mid = (final + first) / 2;
while (final>=first){
if (a[mid] == a[i]) {
final = mid;
break;
}
if (a[mid] > a[i]) {
final = mid-1;
mid = (final + first) / 2;
}
else {
first = mid+1;
mid = (final + first) / 2;
}
}
//每次while结束final就在该插入的位置前一个
for (int j = i-1; j >final; j--) {
a[j + 1] = a[j];
}
a[final+1] = tmp;
}
}
二路排序
//二路排序
void TwowaySort(int* a,int n) {
int right = n;
int left = 0;
int* tmp = (int*)malloc(sizeof(int) * n);
tmp[0] = a[left];
int first, last;
first = last = 0;
for (int i = left + 1; i < right; ++i){
if (a[i] < tmp[first]){
first = (first - 1 + n) % n;
tmp[first] = a[i];
}
else if (a[i] > tmp[last]){
last++;
tmp[last] = a[i];
}
else{
int end = last;
while (a[i] < tmp[end]){
tmp[(end + 1) % n] = tmp[end];
end = (end - 1 + n) % n;
}
tmp[(end + 1) % n] = a[i];
last++;
}
}
int k = 0;
for (int i = first; k < n; ++k){
a[k] = tmp[i];
i = (i + 1) % n;
}
free(tmp);
}
冒泡排序
//冒泡排序
void BubbleSort(int* a, int n) {
for (int i = 0; i < n; i++) {
for (int j = n - 1; j > i; j--) {
if (a[j] < a[j - 1]) {
int tmp = a[j];
a[j] = a[j - 1];
a[j - 1] = tmp;
}
}
}
}
选择排序
//选择排序
void SelectSort(int* a, int n) {
int min = 0;
for (int i = 0; i < n; i++) {
int j = i;
int m = 0;
min = a[i];
for (; j < n; j++) {
if (a[j] <= min) {
min = a[j];
m = j;
}
}
a[m] = a[i];
a[i] = min;
}
}
希尔排序
//希尔排序
void ShellSort(int* a, int n) {
int interval = n / 2;
while (interval>=1){
//for (int i = interval; i < n; i++) {
// int temp = a[i];
// int j = i;
// //把a[i]所在组前面比a[i]大的依次往后移,直到找到比a[i]小的或者到组头了
// while (a[j - interval] > temp && j - interval >= 0) {
// a[j] = a[j - interval];
// j -= interval;
// }
// a[j] = temp;
//}
for (int i = interval; i >= 0; i--) {
for (int j = i; j < n; j = j + interval) {
int tmp = a[j];
while (a[j - interval] > a[j] && j - interval >= 0){
a[j] = a[j - interval];
j -= interval;
}
a[j] = tmp;
}
}
interval = interval / 2;
}
}
堆排序
//堆排序,数组视为堆结构
//创建大堆,然后把堆顶和堆尾交换,视堆元素少一,再创建大堆,再交换,再减堆尾,依次可得
void _ShiftDown(int ar[], int left, int right, int start)
{
int n = right - left;
int i = start; //父节点,建堆时从后往前依次,排序时start传0第一个即可
int j = 2*i + 1; //左子树
while(j < n)
{
if(j+1<n && ar[j]<ar[j+1])
j++;
if(ar[i] < ar[j])
{
int tmp =ar[i];
ar[i] = ar[j];
ar[j]=tmp;
i = j;
j = 2*i+1;
}
}
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--;
}
}
快速排序
//快速排序hoare版本
int PartSort1(int* a, int left, int right){
int key = a[left];
int i = left;
int j = right-1;
int tmp = 0;
while (i < j) {
while (a[j] >= key && i < j) {
j--;
}//直到找到后面比key值小的就交交换
/*tmp = a[i];
a[i] = a[j];
a[j] = tmp;
这里可以不写,可以等到后面i找到大于key的时候再交换*/
while (a[i] < key && i < j) {
i++;
}//同理,这样key就左右横条最终位于中间大小位置
tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
return i;
}
// 快速排序挖坑法,避免了数据交换
int PartSort2(int* a, int left, int right) {
if (begin >= end)//当只有一个数据或是序列不存在时,不需要进行操作
return;
int left = begin;//L
int right = end;//R
int key = a[left];//在最左边形成一个坑位
while (left < right)
{
//right向左,找小
while (left < right && a[right] >= key)
{
right--;
}
//填坑
a[left] = a[right];
//left向右,找大
while (left < right && a[left] <= key)
{
left++;
}
//填坑
a[right] = a[left];
}
int meeti = left;//L和R的相遇点
a[meeti] = key;//将key抛入坑位
}
// 快速排序前后"指针"法,后指针碰到小于key值的若前指针不等于后指针就交换
int PartSort3(int* a, int left, int right) {
int i = left;
int j = left + 1;
int m = a[left];
while ( j < right) {
if (a[j] <= m) {
i++;
if (i != j) {
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
}
j++;
}
int t = a[left];
a[left] = a[i];
a[i] = t;
return i;
}
void QuickSort(int* a, int left, int right) {
if (left >= right)
return;
int mid = PartSort2(a,left,right);
QuickSort(a,mid+1,right);
QuickSort(a,left,mid);
}
// 快速排序,利用链栈(队列也行)非递归实现
void QuickSortNonR(int* a, int left, int right) {
//LinkStack st;
//LinkStackInit(&st);
//LinkStackPush(&st, left);
//LinkStackPush(&st, right);
//while (!LinkStackEmpty(&st))
//{
// right = LinkStackTop(&st);
// LinkStackPop(&st);
// left = LinkStackTop(&st);
// LinkStackPop(&st);
// if (right - left <= 1)
// continue;
// int pos = _Partition_3(ar, left, right);
// LinkStackPush(&st, pos + 1); //
// LinkStackPush(&st, right);
// LinkStackPush(&st, left);
// LinkStackPush(&st, pos);
//}
}
归并排序
//归并排序
void _MergeSort(int* a,int left,int right,int* tmp) {
if (left >= right)
return;//剩一个元素时直接返回,上一层递归两个元素,下面归并时就按照两个元素开始平分两组数据然后排序
int mid = (left + right) / 2;
_MergeSort(a, left, mid, tmp);
_MergeSort(a, 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 (a[begin1] < a[begin2])
tmp[k++] = a[begin1++];
else
tmp[k++] = a[begin2++];
}//排完某一边
//将剩下没排的另一边全放到tmp后面
while (begin1 <= end1)
tmp[k++] = a[begin1++];
while (begin2 <= end2)
tmp[k++] = a[begin2++];
//因为是递归的,所以每次排好就要赋值回原数组,才能使下一次排时两边的数据都是有序的
memcpy(a + left, tmp + left, sizeof(int) * (right - left + 1));
}
void MergeSort(int* a, int n) {
int left = 0;
int right = n-1;
int* tmp =(int*)malloc(sizeof(int) * n);
_MergeSort(a, left, right, tmp);
free(tmp);
}
基数排序
//计数排序
#define wei 2
#define radix 10
List list[radix];
int getweinum(int val,int n) {
int key = val;
while (n>=0){
key = val % 10;
val = val / 10;
n--;
}
return key;
}
void fenfalian(int* a,int right,int n) {
for (int i = 0; i < right; i++) {
int k = getweinum(a[i],n);
ListPushBack(&list[k], a[i]) ;
}
}
void huishou(int* a) {
int j = 0;
for (int i = 0; i < radix; i++) {
while (list[i]!=NULL) {
a[j]=list[i]->data;
list[i] = list[i]->next;
j++;
}
}
for (int i = 0; i < radix; i++) {
ListClear(&list[i]);
}
}
void CountSort(int* a, int n) {
int right = n;
int left = 0;
for (int i = 0; i < radix; i++) {
ListInit(&list[i]);
}
for (int i = 0;i < wei; i++) {
fenfalian(a,right,i);
huishou(a);
}
}
测速函数
//测试每个排序用时
void TestSortTime() {
srand((unsigned int)time(0));
int n = 10000;
int* a = (int*)malloc(sizeof(int) * n);
int* b = (int*)malloc(sizeof(int) * n);
int* c = (int*)malloc(sizeof(int) * n);
for (int i = 0; i < n; i++) {
a[i] = rand();
b[i] = a[i];
c[i] = a[i];
}
unsigned long start = clock();
BTInsertSort(a, n);
unsigned long end = clock();
printf("BTInsertSort:%u\n", end - start);
start = clock();
ShellSort(b, n);
end = clock();
printf("ShellSort:%u\n", end- start);
start = clock();
HeapSort(b, 0,n);
end = clock();
printf("HeapSort:%u\n", end - start);
free(a);
free(b);
free(c);
}