Implementación de código de clasificación de cubos

1. Acerca de la introducción de la clasificación de cubos de una sola pasada y el problema.
Presente una situación simple. Si tenemos varios números enteros (diferentes), y estos números enteros van de 0 a 99, ¿cómo organizar estos números enteros?
De acuerdo con el método de clasificación de barriles, podemos establecer una matriz int barril [100], cada elemento representa un barril, y el subíndice de cada barril representa el número en el barril, como el número 18, lo pondremos en el barril. [18] Entra. Por lo tanto, no es difícil conseguir que si la secuencia numérica a ordenar tiene 40 números, entonces solo necesitamos gastar 40 veces para poner los números en el cubo.
El problema es que si solo hay 2 números en la secuencia numérica, debido a que no sabe cuáles son los dos del 0 al 99, aún necesita abrir una matriz de 100 elementos para usar como un cubo, lo que causa un perdida de espacio. Por eso consideramos que cuantos menos barriles mejor .
Además, lo que consideramos anteriormente es la situación en la que los números en la secuencia numérica son diferentes. Si consideramos la repetición, es posible que necesitemos una matriz para representar el cubo para contener el número repetido. Tome el ejemplo anterior, suponga que solo hay 2 números en la secuencia para ser ordenados (rango 0-99). Dado que cada depósito puede contener estos dos números, cada depósito debe ser una matriz de tamaño 2. Y porque hay 100 depósitos para ser configurado, el costo del espacio es 2 × 100 espacio tipo elemento Cuando hay n números en la secuencia para ordenar, el costo del espacio se convertirá en n × 100. Y sepa que solo hay n espacios que realmente contienen números, por lo que hay mucho espacio porque no hay números, lo que genera un gran desperdicio. Por lo que consideramos que cada bucket está representado por una lista enlazada , y si la hay, se asignará, y si no, no se asignará, evitando así desperdicios de espacio innecesarios.
2. Explicación de la
clasificación de cangilones de múltiples pasadas Cada paso de la clasificación de cangilones de múltiples pasadas consiste en realizar la clasificación de cangilones en una determinada broca, y cada pasada coloca un cierto número en el cangilón de acuerdo con un cierto número.
¿Es de menor a mayor o de mayor a menor?
En primer lugar, necesitamos saber qué hacer después de poner los números en el cubo cada vez. Después de poner los números en el cubo, necesitamos "verter" los números en el cubo, es decir, sobrescribir la secuencia numérica original en orden como la secuencia numérica que se procesará en la siguiente pasada. En el proceso de "vertido", los cubos con diferentes números son fáciles de manejar, siempre y cuando se vierte de pequeño a grande según el número del cubo, pero ¿cómo lidiar con diferentes números en un cubo?
No es difícil darse cuenta de que en este momento debemos ordenar los números en el mismo cubo según el tamaño del siguiente dígito. Los pequeños se colocan delante del cubo y los grandes detrás del cubo. Luego sólo tenemos que invertir el cubo. Está bien verter en el orden de adelante hacia atrás. Dado que el orden de dos números en el mismo cubo está determinado por el orden de procesamiento de los dos números (es decir, el primero procesado primero, el segundo procesado segundo), y el orden de procesamiento es que los dos números estén en La secuencia en el pendiente secuencia de este viaje. Esto significa que la secuencia a procesar para este viaje debe haberse organizado en el siguiente orden. Por lo tanto, requerimos que nuestra clasificación de cubos de múltiples pasadas sea un viaje de menor a mayor.
A continuación, se muestra un ejemplo para mostrar la explicación anterior para facilitar su comprensión:
Un ejemplo concreto
3. Implementación de código de la clasificación de depósitos

#include "List.h"
void Initial(List barral[])
{
    
    
	int i = 0;
	for (i = 0; i < 10; i++)
		barral[i] = MakeList();
}

void PrintNum(List L)
{
    
    
	Position islast=Last(L);
	Position P = L->next;
	while (P != islast)
	{
    
    
		printf("%d ", P->number);
		P = P->next;
	}
}

int main()
{
    
    
	int addone;
	int i, j;
	Position P;
	/*
		设置木桶,每个桶是一个链表,下面是对木桶含义的解释:
		确定一位(个位、十位或者百位),10个元素分别代表10个木桶,每一个木桶用来装在这位上数字相同的三位数.
		如:个位设置10个木桶,假设有116和226这两个数字,则我们把它们装在这10个桶中的6号桶(barrel[6])里
	*/
	List barral[10] = {
    
     0 };
	Initial(barral);
	
	//创建一个链表用来装待排序的数字
	List number=MakeList();
	printf("请输入多个三位数以内的数字,我们将为你排序:>\n");
	//ctrl+z结束输入
	while (scanf("%d", &addone) != EOF)
	{
    
    
		//将待排序的数字插入number这个链表中
		Insert(number, Last(number), addone);
	}
	//j表示当前处理的位,从个位先开始(j=1:个位、j=2:十位、j=3:百位)将每个待排序的数字按照当前位上的数字,装进这个位中的10个桶中的一个
	for (j = 1; j <= 3;j++)
	{
    
    
		//遍历处理每一个number中的待排序数字
		for (P = number->next; P != NULL; P = P->next)
		{
    
    
			//m表示当前处理位的权重(如:j=1表示个位,那么个位权重就是1,即m=1)
			int m=(int)pow(10,j-1);
			//i表示这个待处理的三位数在当前位上的数字
			int i = ((P->number) / m)%10;
			//将其放到当前位对应的桶里面去(放到对应桶的末尾)
			Insert(barral[i], Last(barral[i]), P->number);
		}
		/*
			至此所有数字都按照当前位的数字放入了当前位的10个桶中对应的某一个桶里去了,接下来更新装有待排序的三位数的number链表的顺序
		*/
		
		//首先将旧的number链表清空
		MakeEmpty(number);

		//然后把木桶里按照当前位的数字大小装好的三位数按从小到大依次放入number链表中,作为下一次循环的待排序数字序列
		
		//这里的i指的是当前位数字为i的木桶,这里是遍历i,将每个i对应的木桶里的三位数放入number链表中
		for (i = 0; i < 10; i++)
		{
    
    
			P = barral[i]->next;
			while (P)
			{
    
    
				Insert(number, Last(number), P->number);
				P = P->next;
			}
			/*
				barral[i]这个木桶里的三位数都放到number里去后,就把它清空以供下一次循环使用(下一个循环中,作为装下一位数字为i的三位数的桶)
				比如:barral[1]在当前这个外层循环中表示个位数字为1的桶,等到下一个外层循环后,barral[1]便作为十位数字为1的桶了
			*/
			MakeEmpty(barral[i]);
		}
	}
	//等到个位十位百位依次排序后,最后number中的顺序就是从小到大的顺序了
	PrintNum(number);
	return 0;
}

List.h 和 List.c

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<math.h>

#ifndef LIST_H
#define LIST_H
struct Node;
typedef struct Node* ptrNode;
typedef ptrNode Position;
typedef ptrNode List;


List MakeList();
void MakeEmpty(List L);
int IsEmpty(List L);
int Find(List L, Position P);
Position FindPositon(List L, int x);
Position FindPrevious(List L, int check);
Position First(List L);
Position Last(List L);
void Insert(List L, Position P,int addone);
void Delete(List L, int popone);

struct Node{
    
    
	int number;
	Position next;
};

#endif
#include "List.h"

List MakeList()
{
    
    
	List L = (List)malloc(sizeof(struct Node));
	L->next = NULL;
	return L;
}

void MakeEmpty(List L)
{
    
    
	Position P=L->next;
	Position tmp;
	L->next = NULL;
	while (P)
	{
    
    
		tmp = P;
		P = P->next;
		free(tmp);
	}
}

int IsEmpty(List L)
{
    
    
	return (!L->next)?1:0;
}

Position First(List L)
{
    
    
	return L->next;
}

Position Last(List L)
{
    
    
	Position P = L;
	while (P->next!=NULL)
		P = P->next;
	return P;
}

int Find(List L, Position P)
{
    
    
	Position tmp = L->next;
	while (tmp != NULL&&tmp != P)
		P = P->next;
	if (tmp)
		return 1;
	else
		return 0;
}

Position FindPosition(List L, int x)
{
    
    
	int i=1;
	Position P = L->next;
	while (P && i != x)
	{
    
    
		P = P->next;
		x++;
	}
	return P;
}

Position FindPrevious(List L, int check)
{
    
    
	Position P = L;
	while ( P->next && P->next->number != check)
		P = P->next;
	if (!P->next)
		return NULL;
	else
		return P;
}

void Insert(List L, Position P, int addone)
{
    
    
	Position tmp;
	tmp = malloc(sizeof(struct Node));
	if (tmp != NULL)
	{
    
    
		tmp->next = P->next;
		tmp->number = addone;
		P->next = tmp;
	}
}

void Delete(List L, int popone)
{
    
    
	Position P = FindPrevious(L, popone);
	if (P)
	{
    
    
		Position tmp = P->next;
		P->next = tmp->next;
		free(tmp);
	}
}

Supongo que te gusta

Origin blog.csdn.net/qq_51690757/article/details/112990034
Recomendado
Clasificación