基于C语言实现的
其中堆排序和循环快排使用到栈。
stack.h:
#pragma once
typedef int STDataType;
typedef struct Stack
{
STDataType* arr;
int size;
int capacity;
}Stack;
void StackInit(Stack* s, int capacity);
void StackPush(Stack* s,STDataType data);
void StackPop(Stack* s);
STDataType StackTop(Stack* s);
int StackEmpty(Stack* s);
int StackSize(Stack* s);
int StackCapacity(Stack* s);
void StackDestroy(Stack* s);
void CheckCapacity(Stack* s);
stack.c:
#include "stack.h"
#include <stdio.h>
#include <malloc.h>
#include <assert.h>
void StackInit(Stack* s,int capacity) {
assert(s);
s->arr = (STDataType*)malloc(sizeof(STDataType)*capacity);
if (s->arr == NULL)
{
assert(0);
return;
}
s->capacity = capacity;
s->size = 0;
}
void StackPush(Stack* s,STDataType data) {
assert(s);
if (s->capacity == s->size)
{
CheckCapacity(s);
}
s->arr[s->size++] = data;
}
void StackPop(Stack* s) {
assert(s);
if (StackEmpty(s))
return;
s->size -= 1;
}
STDataType StackTop(Stack* s) {
assert(s);
return s->arr[s->size-1];
}
int StackEmpty(Stack* s) {
assert(s);
return s->size == 0;
}
int StackSize(Stack* s) {
assert(s);
return s->size;
}
int StackCapacity(Stack* s) {
assert(s);
return s->capacity;
}
void StackDestroy(Stack* s) {
if (s->arr) {
free(s->arr);
}
s->capacity = 0;
s->size = 0;
}
void CheckCapacity(Stack* s) {
assert(s);
int newcapacity = 2 * s->capacity;
STDataType* pTemp = (STDataType*)malloc(sizeof(STDataType)*newcapacity);
if (pTemp == NULL) {
assert(0);
return;
}
for (int i = 0; i < s->size; i++) {
pTemp[i] = s->arr[i];
}
free(s->arr);
s->arr = pTemp;
s->capacity = newcapacity;
}
Sort.h文件:
#pragma once
//时间复杂度:O(N^2)
//空间复杂度:O(1)
//稳定性;稳定
//冒泡排序
void BubbleSort(int arr[], int len);
//应用场景;数据量小,接近有序
//时间复杂度:O(N^2)
//空间复杂度:O(1)
//稳定性;稳定
//插入排序
void InsertSort(int arr[], int len);
void InsertSort1(int arr[], int left, int right) ;
//应用场景:数据量大,无序
//时间复杂度:O(N^1.25 -1.6N^1.25)
//空间复杂度:O(1)
//稳定性;不稳定
//希尔排序
void ShellSort(int arr[], int len);
//时间复杂度:O(N^2)
//空间复杂度:O(1)
//稳定性;稳定
//选择排序
void SelectSort(int arr[], int len);
void SelectSort1(int arr[], int len);
//时间复杂度:O(NlogN)
//空间复杂度:O(1)
//稳定性:不稳定
//大堆升序,小堆降序
//Top k
//堆排序
void HeapSort(int arr[], int len);
//时间复杂度:O(NlogN)
//空间复杂度:O(N)
//稳定性:不稳定
//优化后的快排
void QuickSort(int arr[], int left, int right);
void MergeData(int arr[], int left, int mid, int right,int* temp);
//时间复杂度:O(NlogN)
//空间复杂度:O(N)
//稳定性:稳定
//归并排序 封装对外接口
void MergeSort(int arr[], int len);
void _MergeSort(int arr[], int left, int right,int* temp);
void MergeSortNor(int arr[], int len);
//时间复杂度:O(N)
//空间复杂度:O(N)
//稳定性:稳定
//计数排序
void CountSort(int arr[], int len);
//优化分割 三数取中法
int GetMiddleIndex(int arr[], int left, int right);
//三种分割区间方法
int Partion1(int arr[], int left, int right);
int Partion2(int arr[], int left, int right);
int Partion3(int arr[], int left, int right);
Sort.c:
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#include <assert.h>
#include <string.h>
//打印函数
void PrintfArray(int arr[],int len) {
for (int i = 0; i < len;++i) {
printf("%d ",arr[i]);
}
printf("\n");
}
//交换函数
void Swap(int* a, int* b) {
int tmp = *a;
* a = *b;
* b = tmp;
}
//时间复杂度:O(N^2)
//空间复杂度:O(1)
//稳定性;稳定
int flag = 0;//0表示没有排序好 //稍加优化的冒泡排序 |~
void BubbleSort(int arr[], int len) {
flag = 1;
for (int i = 0; i < len; i++) {
for (int j = len - 1; j > i; j--) {
if (arr[j - 1] > arr[j]) {
flag = 0;
Swap(&arr[j - 1],&arr[j]);
}
}
}
}
//时间复杂度:O(N^2)
//空间复杂度:O(1)
//稳定性;稳定
void InsertSort(int arr[], int len) {
for (int i = 1; i < len; ++i) {
//待插入元素
int key = arr[i];
//找key的插入位置:与前面已经排好的元素比较
int end = i - 1;
while (end >= 0 && key < arr[end]) {
arr[end + 1] = arr[end];
end -= 1;
}
//插入元素
arr[end + 1] = key;
}
}
//时间复杂度:O(N^1.25 -1.6N^1.25)
//空间复杂度:O(1)
//稳定性;不稳定
void ShellSort(int arr[], int len) {
int gap = len;
while (gap>0) {
gap = gap / 3 + 1;//O(N^1.25 -1.6N^1.25)时间复杂度
for (int i = gap; i < len; ++i) {
//待插入元素
int key = arr[i];
//找key的插入位置:与前面已经排好的元素比较
int end = i - gap;
while (end >= 0 && key < arr[end]) {
arr[end + gap] = arr[end];
end -= gap;
}
//插入元素
arr[end + gap] = key;
}
gap -= 1;
}
}
//堆排序向下调整
void AdjustDown(int arr[], int len, int parent) {
int child = parent * 2 + 1;
while (child < len) {
if (child + 1 < len && arr[child + 1] > arr[child]) {
child += 1;
}
if (arr[child] > arr[parent]) {
Swap(&arr[child], &arr[parent]);
parent = child;
child = parent * 2 + 1;
}
else
return;
}
}
//时间复杂度:O(NlogN)
//空间复杂度:O(1)
//稳定性:不稳定
//Top k
void HeapSort(int arr[],int len) {
//建堆找倒数第一个非叶子节点
int root = ((len - 2) >> 1);
for (; root >= 0; --root) {
AdjustDown(arr, len, root);
}
//排序 堆删除思想
int end = len - 1;
while (end) {
Swap(&arr[0], &arr[end]);
AdjustDown(arr, end, 0);
end--;
}
}
//缺陷:进行了重复比较
void SelectSort1(int arr[], int len) {
for (int i = 0; i < len - 1;++i) {
int Maxpos = 0;
for (int j = 1; j < len - i;++j) {
if (arr[j] > arr[Maxpos]) {
Maxpos = j;
}
if(Maxpos != len-i-1)
Swap(&arr[len-i-1], &arr[Maxpos]);
}
}
}
//时间复杂度:O(N^2)
//空间复杂度:O(1)
//稳定性;稳定
void SelectSort(int arr[], int len) {
int begin = 0;
int end = len - 1;
while (begin<end) {
int Maxpos = begin;
int Minpos = begin;
int index = begin+1;
while (index<=end) {
if (arr[index] > arr[Maxpos])
Maxpos = index;
if (arr[index] < arr[Minpos])
Minpos = index;
index++;
}
if (Minpos == end)
Minpos = Maxpos;
//可能会覆盖小元素位置,所以要更新Minpos位置
if (Maxpos != end)
Swap(&arr[Maxpos], &arr[end]);
if (Minpos != begin)
Swap(&arr[Minpos], &arr[begin]);
begin++;
end--;
}
}
//优化分割 三数取中法
int GetMiddleIndex(int arr[], int left, int right) {
int mid = left + ((right - left) >> 1);
if (arr[left] < arr[right - 1]) {
if (arr[mid] < arr[left])
return left;
else if (arr[mid] > arr[right - 1])
return right - 1;
else
return mid;
}
else {
if (arr[mid] > arr[left])
return left;
else if (arr[mid] < arr[right - 1])
return right - 1;
else
return mid;
}
}
//分割方式
//第一种:hoare
int Partion1(int arr[], int left, int right) {
int begin = left;
int end = right-1;
int mid = GetMiddleIndex(arr, left, right);
Swap(&arr[mid], &arr[right - 1]);
int key = arr[right-1];
while (begin<end) {
while (begin < end && arr[begin] <= key)
begin++;
while (begin < end && arr[end] >= key)
end--;
if(begin != end)
Swap(&arr[begin], &arr[end]);
}
if(begin != right-1)
Swap(&arr[right - 1], &arr[begin]);
return begin;
}
//第二种:挖坑法
int Partion2(int arr[], int left, int right) {
int begin = left;
int end = right - 1;
int mid = GetMiddleIndex(arr, left, right);
Swap(&arr[mid], &arr[right - 1]);
int key = arr[right - 1];
while (begin<end) {
while (begin < end && arr[begin] <= key)
begin++;
if (begin < end) {
arr[end] = arr[begin];
end--;
}
while (begin < end && arr[end] >= key)
end--;
if (begin < end) {
arr[begin] = arr[end];
begin++;
}
}
arr[begin] = key;
return begin;
}
//第三种:两个指针
int Partion3(int arr[], int left, int right) {
int cur = left;
int pre = cur - 1;
int mid = GetMiddleIndex(arr, left, right);
Swap(&arr[mid], &arr[right - 1]);
int key = arr[right - 1];
while (cur < right) {
if (arr[cur] < key && ++pre != cur)
Swap(&arr[pre], &arr[cur]);
cur++;
}
if(++pre != right)//防止越界
Swap(&arr[pre], &arr[right - 1]);
return pre;
}
void QuickSort(int arr[], int left, int right) {
//[ )左闭右开
if (right-left>1) {
//分割左右区间
int div = Partion3(arr, left, right);
QuickSort(arr, left, div);
QuickSort(arr, div + 1, right);
}
}
//优化快排实现(相互配合)的调用接口
//修改的插入排序
void InsertSort1(int arr[], int left, int right) {
for (int i = left; i < right; ++i) {
//待插入元素
int key = arr[i];
//找key的插入位置:与前面已经排好的元素比较
int end = i - 1;
while (end >= 0 && key < arr[end]) {
arr[end + 1] = arr[end];
end -= 1;
}
//插入元素
arr[end + 1] = key;
}
}
//应用场景(数据量大,随机序列)
//优化之后的快排
//三数取中法
//减小递归深度 数据长度小于16时,用直接插入排序替换
//时间复杂度:O(NlogN)
//空间复杂度:O(N)
//稳定性:不稳定
void QuickSort1(int arr[], int left, int right) {
//[ )左闭右开
if (right - left < 16)
InsertSort1(arr, left, right);
else {
//分割左右区间
int div = Partion3(arr, left, right);
QuickSort1(arr, left, div);
QuickSort1(arr, div + 1, right);
}
}
#include "stack.h"
void QuickSortNor(int arr[],int len) {
int left = 0;
int right = len;
Stack s;
StackInit(&s,len);
StackPush(&s, right);
StackPush(&s, left);
int div = Partion3(arr, left, right);
while (!StackEmpty(&s)) {
left = StackTop(&s);
StackPop(&s);
right = StackTop(&s);
StackPop(&s);
if (right - left > 1) {
int div = Partion3(arr, left, right);
//[left,div)
//[div+1,right)
//保存右半部分
StackPush(&s, right);
StackPush(&s, div + 1);
//保存左半部分
StackPush(&s, div);
StackPush(&s, left);
}
}
}
void MergeData(int arr[],int left,int mid,int right,int* temp) {
int begin1 = left, end1 = mid;
int begin2 = mid, end2 = right;
int index = left;
while (begin1 < end1 && begin2 < end2) {
if (arr[begin1] < arr[begin2])
temp[index++] = arr[begin1++];
else
temp[index++] = arr[begin2++];
}
while (begin1 < end1)
temp[index++] = arr[begin1++];
while (begin2 < end2)
temp[index++] = arr[begin2++];
}
void _MergeSort(int arr[], int left, int right,int* temp) {
if (right - left > 1) {
int mid = left + ((right - left) >> 1);
//[left,mid)
//[mid,right)
_MergeSort(arr, left, mid,temp);
_MergeSort(arr, mid, right,temp);
MergeData(arr, left, mid, right,temp);
memcpy(arr+left, temp+left, sizeof(int)*(right - left));
}
}
void MergeSort(int arr[], int len) {
int* temp = (int*)malloc(sizeof(int)*len);
if (NULL == temp) {
assert(0);
return;
}
_MergeSort(arr, 0, len, temp);
free(temp);
}
//时间复杂度:O(NlogN)
//空间复杂度:O(N)
//稳定性:稳定
void MergeSortNor(int arr[], int len) {
int* temp = (int*)malloc(sizeof(int)*len);
if (NULL == temp) {
assert(0);
return;
}
int gap = 1;
while (gap < len) {
for (int i = 0; i < len; i += 2 * gap) {
int left = i;
int mid = left + gap;
if (mid >= len)
mid = len;
int right = mid + gap;
if (right >= len)
right = len;
MergeData(arr, left, mid, right, temp);
}
memcpy(arr, temp, sizeof(int)*len);
gap *= 2;
}
free(temp);
}
void CountSort(int arr[],int len) {
//找数据范围
int minvalue = arr[0];
int maxvalue = arr[0];
for (int i = 0; i < len;++i) {
if (arr[i] >= maxvalue)
maxvalue = arr[i];
if (arr[i] < minvalue)
minvalue = arr[i];
}
int range = maxvalue - minvalue + 1;
int* pCount = (int*)malloc(sizeof(int)*range);
if (NULL == pCount) {
assert(0);
return;
}
memset(pCount, 0, sizeof(int)*range);
//统计元素出现个数
for (int i = 0; i < len;++i) {
pCount[arr[i] - minvalue]++;
}
//回收元素
int index = 0;
for (int i = 0; i < range;++i) {
while (pCount[i]) {
arr[index++] = i + minvalue;
pCount[i]--;
}
}
free(pCount);
}
int main() {
//int arr[] = { 3,5,2,9,1,7,6,0,8,4 };
//int arr[] = { 2,5,1,7,4,6,9,3,8,0 };
//int arr[] = { 3,4,2,9,1,7,6,0,8,5 };
int arr[] = { 2,1,2,5,4,1,2,1,5,4,2,5,4,1,5,2,4,2,1,5,1,4,5,5,4 };
PrintfArray(arr, sizeof(arr) / sizeof(arr[0]));
//BubbleSort(arr, sizeof(arr) / sizeof(arr[0]));
//InsertSort(arr, sizeof(arr) / sizeof(arr[0]));
//ShellSort(arr, sizeof(arr) / sizeof(arr[0]));
//SelectSort1(arr, sizeof(arr) / sizeof(arr[0]));
//SelectSort(arr, sizeof(arr) / sizeof(arr[0]));
//QuickSort(arr, 0,sizeof(arr) / sizeof(arr[0]));
QuickSort1(arr, 0, sizeof(arr) / sizeof(arr[0]));
//MergeSort(arr, sizeof(arr) / sizeof(arr[0]));
//MergeSortNor(arr, sizeof(arr) / sizeof(arr[0]));
//CountSort(arr, sizeof(arr) / sizeof(arr[0]));
//HeapSort(arr, sizeof(arr) / sizeof(arr[0]));
//QuickSortNor(arr, sizeof(arr) / sizeof(arr[0]));
PrintfArray(arr, sizeof(arr) / sizeof(arr[0]));
return 0;
}
测试结果: