[Data structure] Outer sorting, radix sorting and counting sorting

Table of contents

Common sorting algorithms::

                                1. Outer sort

                                2. Radix sort

                                3. Counting sort


Common sorting algorithms::

1. Outer sort

#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. Radix sort

//基数排序
//基数排序的思想: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. Counting sort 

Idea: Counting sorting, also known as the pigeonhole principle, is a modified application of the hash direct addressing method. Steps:
1. Count the number of occurrences of the same element
2. Recycle the sequence to the original sequence according to the statistical results
//非比较排序:基数排序 计数排序 桶排序
//计数排序
//思想:数组中的每个位置是下标对应的值的次数 一个值出现几次 它对应位置就会++几次
//所开空间数为max-min+1个  a[i]-min就是映射的相对位置
//适用场景:适用范围相对集中的数据进行排序处理(负数也可以)
//时间复杂度是O(N+range)
//空间复杂度是O(range)
//稳定性:稳定
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
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);
}

Guess you like

Origin blog.csdn.net/qq_66767938/article/details/129758319