文章目录
- 1.总结
- 2.总代码
- 2.1Stack.h
- 2.2Stack.c
- 2.3Sort.h
- 2.4Sort.c
- 2.5Test.c
1.总结
2.总代码
点击 排序(C) 跳转码云获取完整代码
2.1Stack.h
#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>
//静态栈
/*
#define N 10
typedef int STDataType;
typedef struct Stack
{
STDataType a[N];
int top;
}ST;
*/
typedef int STDataType;
typedef struct Stack
{
int top; //栈顶位置
int capacity;
STDataType* a;
}ST;
//初始化
void StackInit(ST* ps);
//销毁
void StackDestroy(ST* ps);
//压栈
void StackPush(ST* ps, STDataType x);
//出栈
void StackPop(ST* ps);
//栈顶数据
STDataType StackTop(ST* ps);
//判空
bool StackEmpty(ST* ps);
//栈大小
int StackSize(ST* ps);
2.2Stack.c
#include "Stack.h"
//初始化
void StackInit(ST* ps)
{
assert(ps);
ps->a = NULL;
ps->top = 0;
ps->capacity = 0;
}
//销毁
void StackDestroy(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = ps->capacity = 0;
}
//压栈
void StackPush(ST* ps, STDataType x)
{
assert(ps);
if (ps->top == ps->capacity)
{
int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * newCapacity);
if (tmp == NULL)
{
printf("realloc fail\n");
exit(-1);
}
ps->a = tmp;
ps->capacity = newCapacity;
}
ps->a[ps->top] = x;
ps->top++;
}
//出栈
void StackPop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
ps->top--;
}
//取栈顶
STDataType StackTop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
return ps->a[ps->top - 1];
}
//判空
bool StackEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
//栈大小
int StackSize(ST* ps)
{
assert(ps);
return ps->top;
}
2.3Sort.h
#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
//打印函数
void PrintArray(int* a, int n);
//插入排序
void InsertSort(int* a, int n);
//希尔排序
void ShellSort(int* a, int n);
//选择排序
void SelectSort(int* a, int n);
//堆排序
void HeapSort(int* a, int n);
//冒泡排序
void BubbleSort(int* a, int n);
//快速排序
extern int count; //测试快排递归次数
void QuickSort(int* a, int begin, int end);
void QuickSort_NonRecursion(int* a, int begin, int end);
//归并排序
void MergeSort(int* a, int n);
void MergeSort_NonRecursion1(int* a, int n);
void MergeSort_NonRecursion2(int* a, int n);
//计数排序
void CountSort(int* a, int n);
2.4Sort.c
#include"sort.h"
#include"Stack.h"
//打印函数
void PrintArray(int* a, int n)
{
for (int i = 0; i < n; ++i)
{
printf("%d ", a[i]);
}
printf("\n");
}
//插入排序1.0
/*
void InsertSort(int* a, int n)
{
//i: 0 -- 倒数第2个元素
for (int k = 0; k < n - 1; ++k)
{
//end记录i
int end = k;
//tmp记录end后一个值
int tmp = a[end + 1];
//把tmp与tmp前的每一个数比较 若小于则前面数据后移
while (end >= 0)
{
if (tmp < a[end])
{
a[end + 1] = a[end];
--end;
}
else
{
break;
}
}
//遇到<=tmp的数 或 tmp前数据遍历完毕 循环终止 把tmp放到目的地
a[end + 1] = tmp;
}
}
*/
//插入排序2.0--在这个版本中默认第一个已排好序 在内层for中会与i前的比较
//直接插入排序没什么问题 但是在下面的希尔排序 第一个元素不能被默认为已经有序
//所以插入排序3.0更好一些 对下面的代码复用起到很好的作用
/*
void InsertSort(int* a, int n)
{
int k, k, t;
for (k = 1; k < n; k++) //i:1 ~ n-1 a[0]默认已排好序
{
//临时变量t记录a[k]的值 下面程序a[k]会被修改
t = a[k];
//遍历i前所有数据 把比a[k]大的都向后移
for (k = k - 1; k >= 0 && t < a[k]; k--)
a[k + 1] = a[k];
//j的初值为i-1 k!=k-1:i前有比a[k]大的 a[k]移到a[k+1]
//此时内层for循环已终止 表明i前数据已有序 需要把原a[k]插到合适位置
if (k != k - 1)
a[k + 1] = t;
}
}
*/
//插入排序3.0
void InsertSort(int* a, int n)
{
int i, j, t;
for (i = 0; i < n - 1; i++)
{
t = a[i + 1];
for (j = i; j >= 0 && t < a[j]; j--)
a[j + 1] = a[j];
if (j != i)
a[j + 1] = t;
}
}
//希尔排序1.0
/*
void ShellSort(int* a, int n)
{
int x = 3;
for (int k = 0; k < x; ++k)
{
for (int k = k; k < n - x; k += x)
{
int end = k;
int tmp = a[end + x];
while (end >= 0)
{
if (tmp < a[end])
{
a[end + x] = a[end];
end -= x;
}
else
{
break;
}
}
a[end + x] = tmp;
}
}
PrintArray(a, n);
}
*/
//希尔排序2.0
/*
void ShellSort(int* a, int n)
{
int x = n;
while (x > 1)
{
x = x / 3 + 1;
for (int k = 0; k < n - x; ++k)
{
int end = k;
int tmp = a[end + x];
while (end >= 0)
{
if (tmp < a[end])
{
a[end + x] = a[end];
end -= x;
}
else
{
break;
}
}
a[end + x] = tmp;
}
printf("x:%d->", x);
PrintArray(a, n);
}
}
*/
//希尔排序3.0
void ShellSort(int* a, int n)
{
int gap = n;
while (gap > 1)
{
gap = gap / 3 + 1;
int i, j, t;
//printf("x:%d->", x);
//PrintArray(a, n);
for (i = 0; i < n - gap ; ++i)
{
t = a[i + gap];
for (j = i ; j >= 0 && t < a[j]; j-=gap)
{
a[j + gap] = a[j];
}
if (j != i)
a[j + gap] = t;
}
//printf("x:%d->", x);
//PrintArray(a, n);
//printf("\n");
}
}
void Swap(int* a, int* b)
{
if (*a == *b)
return;
else
{
int t = *a;
*a = *b;
*b = t;
}
}
//插入排序: O(num)~O(num^2)
//选择排序:O(num^2)~O(num^2)
//当数据趋于有序或随机(可能部分有序) 插排更优
void SelectSort(int* a, int n)
{
assert(a);
//i:数据头 j:数据尾
for (int i = 0, j = n - 1; i < j; ++i, --j)
{
//假设最大值/最小值下标为i
int m = i, M = i;
//遍历i后到j的所有数据 确定real_m/M
for (int k = i + 1; k <= j; ++k)
{
if (a[k] < a[m])
m = k;
if (a[k] > a[M])
M = k;
}
//小值换到数据头
Swap(&a[i], &a[m]);
//特殊情况需重新匹配
if (i == M)
{
M = m;
}
//大值换到数据尾
Swap(&a[j], &a[M]);
}
}
//堆排序 -- 升序建大堆 降序建小堆
void AdjustDwon(int* a, int size, int parent)
{
//设左孩子较小
int child = parent * 2 + 1;
//当未达到堆末 进入循环
while (child < size)
{
//确定real小孩子
//if (child + 1 < size && a[child + 1] < a[child]) //小堆
//确定real大孩子
if (child + 1 < size && a[child + 1] > a[child]) //大堆
{
++child;
}
//if (a[parent] > a[child]) //小堆
if (a[parent] < a[child]) //大堆
{
Swap(&a[child], &a[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void HeapSort(int* a, int n)
{
//下调建大堆
for (int i = (n - 1 - 1) / 2; i >= 0; --i)
{
AdjustDwon(a, n, i);
}
//排序
int end = n - 1; //此时end表示堆尾数据的下标
while (end > 0)
{
Swap(&a[0], &a[end]);
AdjustDwon(a, end, 0); //此时end表示传过去数据个数(n-1)
--end;
}
}
//插入排序 O(num)~O(num^2)
//冒泡排序 O(num)~O(num^2)
//当数据有序 二者均为O(num)
//当数据接近有序或局部有序 插排更优
void BubbleSort(int* a, int n)
{
assert(a);
int flag = 1;
for (int i = 0; flag && i < n - 1; ++i)
{
flag = 0;
for (int j = 0; j < n - 1 - i; ++j)
{
if (a[j] > a[j + 1])
{
Swap(&a[j + 1], &a[j]);
flag = 1;
}
}
}
}
//快速排序 O(num * logN)
int count = 0; //测试递归次数
//对任意区间三值取中位数
int GetMid_X(int* a, int begin, int end)
{
int mid = (begin + end) / 2;
if (a[begin] < a[mid])
{
if (a[mid] < a[end])
return mid;
else if (a[begin] < a[end])
return end;
else
return begin;
}
else //a[begin] >= a[mid]
{
if (a[mid] > a[end])
return mid;
else if (a[begin] < a[end])
return begin;
else
return end;
}
}
//霍尔版本
int PartQuickSort1(int* a, int begin, int end)
{
int left = begin, right = end, x = left;
//确定更合适的key
int mid_x = GetMid_X(a, begin, end);
Swap(&a[x], &a[mid_x]);
while (left < right)
{
//右找小
while (left < right && a[right] >= a[x])
--right;
//左找大
while (left < right && a[left] <= a[x])
++left;
Swap(&a[left], &a[right]);
}
Swap(&a[x], &a[left]);
x = left;
return x;
}
//挖坑版本
int PartQuickSort2(int* a, int begin, int end)
{
int x = begin;
//确定更合适的key
int mid_x = GetMid_X(a, begin, end);
Swap(&a[x], &a[mid_x]);
int key = a[x];
while (begin < end)
{
while (begin < end && a[end] >= key)
--end;
a[x] = a[end];
x = end;
while (begin < end && a[begin] <= key)
++begin;
a[x] = a[begin];
x = begin;
}
a[x] = key;
return x;
}
//指针版本
int PartQuickSort3(int* a, int begin, int end)
{ //prv:previous cp:current pointer
int prv = begin, cp = begin + 1, x = begin;
//确定更合适的key
int mid_x = GetMid_X(a, begin, end);
Swap(&a[x], &a[mid_x]);
while (cp <= end)
{
if (a[cp] < a[x] && ++prv != cp)
Swap(&a[prv], &a[cp]);
++cp;
}
Swap(&a[prv], &a[x]);
x = prv;
return x;
}
void QuickSort(int* a, int begin, int end)
{
count++;
//begin:左区间左边界下标
//end :右区间右边界下标
//begin==end:数据量=1 无需排序 直接返回
//begin>end :无效区间 无需排序 直接返回
if (begin >= end)
return;
int x = PartQuickSort3(a, begin, end);
// [begin, x - 1] x [x + 1, end]
QuickSort(a, begin, x - 1);
QuickSort(a, x+1, end);
}
/*
void QuickSort(int* a, int begin, int end)
{
arr++;
if (begin >= end)
return;
if (end - begin > 10)
{
int x = PartQuickSort3(a, begin, end);
// [begin, x-1] x [x+1, end]
QuickSort(a, begin, x - 1);
QuickSort(a, x + 1, end);
}
else
InsertSort(a + begin, end - begin + 1);
}
*/
//非递归版本
void QuickSort_NonRecursion(int* a, int begin, int end)
{
ST st;
StackInit(&st);
StackPush(&st, begin);
StackPush(&st, end);
while (!StackEmpty(&st))
{
int end = StackTop(&st);
StackPop(&st);
int begin = StackTop(&st);
StackPop(&st);
int x = PartQuickSort3(a, begin, end);
if (x + 1 < end)
{
StackPush(&st, x + 1);
StackPush(&st, end);
}
// [begin, x-1] x [x+1, end]
if (begin < x - 1)
{
StackPush(&st, begin);
StackPush(&st, x - 1);
}
}
StackDestroy(&st);
}
//归并排序 时间复杂度:O(num*logN) 空间复杂度:O(num)
void PartMergeSort(int* a, int begin, int end, int* tmp)
{
if (begin >= end)
return;
int mid = (begin + end) / 2;
//[begin, mid] [mid+1, end]
PartMergeSort(a, begin, mid, tmp);
PartMergeSort(a, mid + 1, end, tmp);
//[begin, mid] [mid+1, end]
// [index, mid] [k, end]
int i = begin, j = mid + 1, k = i;
while (i <= mid && j <= end)
{
if (a[i] <= a[j])
tmp[k++] = a[i++];
else
tmp[k++] = a[j++];
}
while (i <= mid)
tmp[k++] = a[i++];
while (j <= end)
tmp[k++] = a[j++];
memcpy(a + begin, tmp + begin, (end - begin + 1) * sizeof(int));
}
void MergeSort(int* a, int n)
{
int* tmp = (int*)malloc(sizeof(int) * n);
if (tmp == NULL)
{
printf("malloc fail\n");
exit(-1);
}
//void PartMergeSort(int* a, int begin, int end, int* tmp);
PartMergeSort(a, 0, n - 1, tmp);
free(tmp);
}
void MergeSort_NonRecursion1(int* a, int n)
{
int* tmp = (int*)malloc(sizeof(int) * n);
if (tmp == NULL)
{
printf("malloc fail\n");
exit(-1);
}
int range = 1;
while (range < n)
{
printf("num = %d ->", range);
for (int index = 0; index < n; index += 2 * range)
{
int i = index, k = i, end = index + range - 1;
int j = index + range, End = index + 2 * range - 1;
//修正边界
if (end >= n)
{
end = n - 1;
j = n;
End = n - 1;
}
else if (j >= n)
{
j = n;
End = n - 1;
}
else if (End >= n)
End = n - 1;
printf("[%d,%d]--[%d, %d] ", i, end, j, End);
//数据排序
while (i <= end && j <= End)
{
if (a[i] <= a[j])
tmp[k++] = a[i++];
else
tmp[k++] = a[j++];
}
while (i <= end)
tmp[k++] = a[i++];
while (j <= End)
tmp[k++] = a[j++];
}
printf("\n");
memcpy(a, tmp, sizeof(int) * n);
range *= 2;
}
free(tmp);
}
void MergeSort_NonRecursion2(int* a, int n)
{
int* tmp = (int*)malloc(sizeof(int) * n);
if (tmp == NULL)
{
printf("malloc fail\n");
exit(-1);
}
int range = 1;
while (range < n)
{
printf("num=%d->", range);
for (int index = 0; index < n; index += 2 * range)
{
int i = index, k = i, end = index + range - 1;
int j = index + range, End = index + 2 * range - 1;
if (end >= n || j >= n)
break;
else if (End >= n)
End = n - 1;
printf("[%d,%d]--[%d,%d] ", i, end, j, End);
int m = End - i + 1;
while (i <= end && j <= End)
{
if (a[i] <= a[j])
tmp[k++] = a[i++];
else
tmp[k++] = a[j++];
}
while (i <= end)
tmp[k++] = a[i++];
while (j <= End)
tmp[k++] = a[j++];
memcpy(a + index, tmp + index, sizeof(int) * m);
}
printf("\n");
range *= 2;
}
free(tmp);
}
//计数排序 时间复杂度:O(max(num, N)) 空间复杂度:O(num)
void CountSort(int* a, int n)
{
//确定最值
int min = a[0], max = a[0];
for (int i = 1; i < n; ++i)
{
if (a[i] < min)
min = a[i];
if (a[i] > max)
max = a[i];
}
int num = max - min + 1; //最多有N个"连续"的数据
//开空间
int* arr = (int*)malloc(sizeof(int) * num);
if (arr == NULL)
{
printf("malloc fail\n");
exit(-1);
}
memset(arr, 0, sizeof(int) * num);
//a的数据映射到arr的下标 arr的值存储对应数据出现次数
for (int i = 0; i < n; ++i)
arr[a[i] - min]++;
for (int i = 0, j = 0; i < num; ++i)
{
while (arr[i]--)
a[j++] = i + min;
}
}
2.5Test.c
#include "Sort.h"
//插入排序
void TestInsertSort()
{
int a[] = { 4, 9,5, 2, 6, 3, 8, 5, 1, 7, 10 };
InsertSort(a, sizeof(a) / sizeof(int));
PrintArray(a, sizeof(a) / sizeof(int));
}
//希尔排序
void TestShellSort()
{
int a[] = { 4, 9, 2, 6, 3, 8, 5, 1, 7, 10 };
ShellSort(a, sizeof(a) / sizeof(int));
PrintArray(a, sizeof(a) / sizeof(int));
}
//选择排序
void TestSelectSort()
{
int a[] = { 4, 9, 2, 6, 3, 8, 5, 1, 7 };
SelectSort(a, sizeof(a) / sizeof(int));
PrintArray(a, sizeof(a) / sizeof(int));
}
//冒泡排序
void TestBubbleSort()
{
int a[] = { 4, 9, 2, 6, 3, 8, 5, 1, 7 };
BubbleSort(a, sizeof(a) / sizeof(int));
PrintArray(a, sizeof(a) / sizeof(int));
}
//快速排序
void TestQuickSort()
{
int a[] = { 4, 9, 2, 6, 3, 8, 5, 1, 7, 10 };
//QuickSort(a, 0, sizeof(a) / sizeof(int)-1);
QuickSort_NonRecursion(a, 0, sizeof(a) / sizeof(int) - 1);
PrintArray(a, sizeof(a) / sizeof(int));
}
//归并排序
void TestMergeSort()
{
int a[] = { 4, 2, 6, 3, 8, 5, 1, 7, 9 };
printf("%u个数据\n", sizeof(a) / sizeof(int));
//MergeSort(a, sizeof(a) / sizeof(int));
//MergeSort_NonRecursion1(a, sizeof(a) / sizeof(int));
MergeSort_NonRecursion2(a, sizeof(a) / sizeof(int));
PrintArray(a, sizeof(a) / sizeof(int));
}
//计数排序
void TestCountSort()
{
int a[] = { -2,-4,-2,4,6,1,3,8,6,9,3 };
CountSort(a, sizeof(a) / sizeof(int));
PrintArray(a, sizeof(a) / sizeof(int));
}
//性能测试
void TestOP()
{
srand(time(0));
const int N = 1000000;
int* a1 = (int*)malloc(sizeof(int) * N);
int* a2 = (int*)malloc(sizeof(int) * N);
int* a3 = (int*)malloc(sizeof(int) * N);
int* a4 = (int*)malloc(sizeof(int) * N);
int* a5 = (int*)malloc(sizeof(int) * N);
int* a6 = (int*)malloc(sizeof(int) * N);
int* a7 = (int*)malloc(sizeof(int) * N);
for (int i = 0; i < N; ++i)
{
a1[i] = rand();
a2[i] = a1[i];
a3[i] = a1[i];
a4[i] = a1[i];
a5[i] = a1[i];
a6[i] = a1[i];
a7[i] = a1[i];
}
//ShellSort(a1, N);
int begin1 = clock();
//InsertSort(a1, N);
int end1 = clock();
int begin2 = clock();
//ShellSort(a3, N);
int end2 = clock();
int begin3 = clock();
//SelectSort(a3, N);
int end3 = clock();
int begin4 = clock();
//HeapSort(a4, N);
int end4 = clock();
int begin5 = clock();
QuickSort(a5, 0, N - 1);
int end5 = clock();
int begin6 = clock();
//MergeSort(a6, N);
int end6 = clock();
int begin7 = clock();
//BubbleSort(a7, N);
int end7 = clock();
printf("InsertSort:%d\n", end1 - begin1);
printf("ShellSort:%d\n", end2 - begin2);
printf("SelectSort:%d\n", end3 - begin3);
printf("HeapSort:%d\n", end4 - begin4);
printf("QuickSort:%d\n", end5 - begin5); printf("count:%d\n", count);
printf("MergeSort:%d\n", end6 - begin6);
printf("BubbleSort:%d\n", end7 - begin7);
free(a1);
free(a2);
free(a3);
free(a4);
free(a5);
free(a6);
free(a7);
}
int main()
{
//插入排序
TestInsertSort();
//希尔排序
//TestShellSort();
//选择排序
//TestSelectSort();
//堆排序
//TestHeapSort();
//冒泡排序
//TestBubbleSort();
//快速排序
//TestQuickSort();
//归并排序
//TestMergeSort();
//计数排序
//TestCountSort();
//性能测试
//TestOP();
return 0;
}