目录
常见的排序算法::
1.外排序
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
//外排序
//思想:大文件平均分割成N份 保证每份的大小可以加载到内存 那么就可以把每个小文件先加载到内存中使用快排排成有序 再写回小文件 那么这时就达到了文件中归并的先行条件
void _MergeFile(const char* file1, const char* file2, const char* mfile)
{
FILE* fout1 = fopen("file", "r");
if (fout1 == NULL)
{
printf("打开文件失败\n");
exit(-1);
}
FILE* fout2 = fopen("file", "r");
if (fout2 == NULL)
{
printf("打开文件失败\n");
exit(-1);
}
FILE* fin = fopen("mfile", "w");
if (fin == NULL)
{
printf("打开文件失败\n");
exit(-1);
}
int num1, num2;
int ret1 = fscanf(fout1, "%d\n", &num1);
int ret2 = fscanf(fout2, "%d\n", &num2);
while (ret1 != EOF && ret2 != EOF)
{
if (num1 < num2)
{
fprintf(fin, "%d\n", num1);
ret1 = fscanf(fout1, "%d\n", &num1);
}
else
{
fprintf(fin, "%d\n", num2);
ret2 = fscanf(fout2, "%d\n", &num2);
}
}
while (ret1 != EOF)
{
fprintf(fin, "%d\n", num1);
ret1 = fscanf(fout1, "%d\n", &num1);
}
while (ret2 != EOF)
{
fprintf(fin, "%d\n", num2);
ret2 = fscanf(fout2, "%d\n", &num2);
}
fclose(fout1);
fclose(fout2);
fclose(fin);
}
void MergeSortFile(const char* file)
{
FILE* fout = fopen("file", "r");
if (fout == NULL)
{
printf("打开文件失败\n");
exit(-1);
}
//分割成一段一段数据
int n = 10;
int a[10];
int i = 0;
int num = 0;
char subfile[20];
int filei = 1;
memset(a, 0, sizeof(int) * n);
while (fscanf(fout, "%d\n", &num) != EOF)
{
if (i < n - 1)
{
a[i++] = num;
}
else
{
a[i] = num;
QuickSort(a, 0, n - 1);
sprintf(subfile, "%d", filei++);
FILE* fin = fopen(subfile, "w");
if (fin == NULL)
{
printf("打开文件失败\n");
exit(-1);
}
for (int i = 0; i < n; i++)
{
fprintf(fin, "%d\n", a[i]);
}
fclose(fin);
i = 0;
memset(a, 0, sizeof(int) * n);
}
}
//利用互相归并到文件,实现整体有序
char mfile[100] = "12";
char file1[100] = "1";
char file2[100] = "2";
for (int i = 0; i <= n; ++i)
{
sprintf(file2, "%d", i);
//读取file1和file2进行归并出mfile
_MergeFile(file1, file2, mfile);
strcpy(file1, mfile);
sprintf(file2, "%d", i + 1);
sprintf(mfile, "%s%d", mfile, i + 1);
}
fclose(fout);
}
2.基数排序
//基数排序
//基数排序的思想:1.分发数据 2.回收数据
#include<iostream>
#include<stdio.h>
#include<queue>
using namespace std;
#define K 3
#define RADIX 10
//[left,right)左闭右开
//定义基数
queue<int> Q[RADIX];
//value:278 k:0
int GetKey(int value, int k)
{
int key = 0;
while (k >= 0)
{
key = value % 10;
value /= 10;
k--;
}
return key;
}
void Distribute(int arr[], int left, int right, int k)
{
for (int i = left; i < right; ++i)
{
int key = GetKey(arr[i], k);
Q[key].push(arr[i]);
}
}
void Collect(int arr[])
{
int k = 0;
for (int i = 0; i < RADIX; ++i)
{
while (!Q[i].empty())
{
arr[k++] = Q[i].front();
Q[i].pop();
}
}
}
void RadixSort(int arr[], int left,int right)
{
for (int i = 0; i < K; ++i)
{
//分发数据
Distribute(arr, left, right, i);
//回收数据
Collect(arr);
}
}
int main()
{
int arr[] = { 278,109,63,930,589,184,505,269,8,83 };
int n = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < n; ++i)
{
printf("%d ", arr[i]);
}
printf("\n");
//基数排序
RadixSort(arr, 0, n);
for (int i = 0; i < n; ++i)
{
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
3.计数排序
思想:计数排序又称为鸽巢原理,是对哈希直接定址法的变形应用。操作步骤:
1.统计相同元素出现次数 2.根据统计的结果将序列回收到原来的序列中
![](https://i-blog.csdnimg.cn/blog_migrate/743a7bab88b05d82d4a9abd0103887cd.png)
//时间复杂度是O(N+range)
//空间复杂度是O(range)
//稳定性:稳定
void CountSort(int* a, int n)
{
int min = a[0];
int max = a[0];
for (int i = 1; i < n; i++)
{
if (a[i] > max)
{
max = a[i];
}
if (a[i] < min)
{
min = a[i];
}
}
int range = max - min + 1;
int* countArr = (int*)malloc(sizeof(int) * range);
memset(countArr, 0, sizeof(int) * range);
//统计次数
for (int i = 0; i < n; i++)
{
countArr[a[i] - min]++;
}
//排序
int index = 0;
for (int j = 0; j < range; j++)
{
while (countArr[j]--)
{
a[index++] = j + min;
}
}
free(countArr);
}
//计数排序的缺陷:只适合整数,不适合浮点数,字符串等数据