Pergunta

Eu estou tentando melhorar meu C ++ através da criação de um programa que terá uma grande quantidade de números entre 1 e 10 ^ 6. Os baldes que vai armazenar os números em cada passagem é uma matriz de nós (onde nó é uma estrutura Criei contendo um valor e um atributo próximo nó).

Após a separação dos números em baldes de acordo com o valor menos significativa, I tem a extremidade de um ponto de balde para o início de outro balde (de modo que pode obter rapidamente os números serem armazenadas sem interromper a ordem). Meu código não tem erros (qualquer compilação ou tempo de execução), mas eu bati em uma parede a respeito de como eu estou indo para resolver os restantes 6 iterações (desde que eu sei o intervalo de números).

O problema que estou tendo é que, inicialmente, os números foram fornecidos para a função Radix Sort na forma de uma matriz int. Após a primeira iteração de triagem, os números estão agora armazenadas na matriz de estruturas. Existe alguma maneira que eu poderia refazer o meu código para que eu tenha apenas um loop for para os 7 iterações, ou eu preciso de um loop que será executado uma vez, e outra volta abaixo dela que será executado 6 vezes antes de retornar o completamente classificadas lista?

#include <iostream>
#include <math.h>
using namespace std;

struct node
{
    int value;
    node *next; 
};

//The 10 buckets to store the intermediary results of every sort
node *bucket[10];
//This serves as the array of pointers to the front of every linked list
node *ptr[10];
//This serves as the array of pointer to the end of every linked list
node *end[10];
node *linkedpointer;
node *item;
node *temp;

void append(int value, int n)
{
    node *temp; 
    item=new node;
    item->value=value;
    item->next=NULL;
    end[n]=item;
    if(bucket[n]->next==NULL)
    {
        cout << "Bucket " << n << " is empty" <<endl;
        bucket[n]->next=item;
        ptr[n]=item;
    }
    else
    {
        cout << "Bucket " << n << " is not empty" <<endl;
        temp=bucket[n];
        while(temp->next!=NULL){
            temp=temp->next;
        }
        temp->next=item;
    }
}

bool isBucketEmpty(int n){
    if(bucket[n]->next!=NULL)
        return false;
    else
        return true;
}
//print the contents of all buckets in order
void printBucket(){
    temp=bucket[0]->next;
    int i=0;
    while(i<10){
        if(temp==NULL){
            i++;
            temp=bucket[i]->next;                       
        }
        else break;

    }
    linkedpointer=temp;
    while(temp!=NULL){
        cout << temp->value <<endl;
        temp=temp->next;
    }
}

void radixSort(int *list, int length){
    int i,j,k,l;
    int x;
    for(i=0;i<10;i++){
        bucket[i]=new node;
        ptr[i]=new node;
        ptr[i]->next=NULL;
        end[i]=new node;
    }
    linkedpointer=new node;

    //Perform radix sort
    for(i=0;i<1;i++){
        for(j=0;j<length;j++){          
            x=(int)(*(list+j)/pow(10,i))%10;            
            append(*(list+j),x);
            printBucket(x); 
        }//End of insertion loop
        k=0,l=1;

        //Linking loop: Link end of one linked list to the front of another
        for(j=0;j<9;j++){
            if(isBucketEmpty(k))
                k++;
            if(isBucketEmpty(l) && l!=9)
                l++;
            if(!isBucketEmpty(k) && !isBucketEmpty(l)){
                end[k]->next=ptr[l];
                k++;
                if(l!=9) l++;   
            }

        }//End of linking for loop

        cout << "Print results" <<endl;
        printBucket();

        for(j=0;j<10;j++)
            bucket[i]->next=NULL;                       
        cout << "End of iteration" <<endl;
    }//End of radix sort loop
}

int main(){
    int testcases,i,input;
    cin >> testcases;
    int list[testcases];
    int *ptr=&list[0];
    for(i=0;i<testcases;i++){
        cin>>list[i];
    }

    radixSort(ptr,testcases);
    return 0;
}
Foi útil?

Solução

Eu acho que você está complicar gravemente a sua solução. É possível implementar radix utilizando a única matriz recebido na entrada, com os baldes em cada passo representado por um conjunto de índices que marcam o índice inicial de cada balde na matriz de entrada.

Na verdade, você pode até mesmo fazê-lo de forma recursiva:

// Sort 'size' number of integers starting at 'input' according to the 'digit'th digit
// For the parameter 'digit', 0 denotes the least significant digit and increases as significance does
void radixSort(int* input, int size, int digit)
{
    if (size == 0)
        return;

    int[10] buckets;    // assuming decimal numbers

    // Sort the array in place while keeping track of bucket starting indices.
    // If bucket[i] is meant to be empty (no numbers with i at the specified digit),
    // then let bucket[i+1] = bucket[i]

    for (int i = 0; i < 10; ++i)
    {
        radixSort(input + buckets[i], buckets[i+1] - buckets[i], digit+1);
    }
}

É claro buckets[i+1] - buckets[i] irá causar um buffer overflow quando i é 9, mas omitiu a verificação extra ou amor de legibilidade; Eu confio em você sabe como lidar com isso.

Com isso, você só tem que radixSort(testcases, sizeof(testcases) / sizeof(testcases[0]), 0) chamada e sua matriz deve ser classificado.

Outras dicas

Para acelerar o processo com melhor gerenciamento de memória, criar uma matriz para as contagens que são convertidos em índices, fazendo uma única passagem sobre a matriz. Atribuir uma segunda matriz de temperatura do mesmo tamanho que a matriz original, e radix tipo entre as duas matrizes até que a matriz é classificada. Se um número ímpar de radix tipo passa é realizada, em seguida, a matriz temperatura terá de ser copiada de volta para a matriz original no final.

Para acelerar ainda mais o processo, uso base 256 em vez de base 10 para o tipo radix. Isso leva apenas 1 passagem de digitalização para criar a matriz e 4 radix sort passa a fazer o tipo. Código Exemplo:

typedef unsigned int uint32_t;

uint32_t * RadixSort(uint32_t * a, size_t count)
{
size_t mIndex[4][256] = {0};            // count / index matrix
uint32_t * b = new uint32_t [COUNT];    // allocate temp array
size_t i,j,m,n;
uint32_t u;
    for(i = 0; i < count; i++){         // generate histograms
        u = a[i];
        for(j = 0; j < 4; j++){
            mIndex[j][(size_t)(u & 0xff)]++;
            u >>= 8;
        }       
    }
    for(j = 0; j < 4; j++){             // convert to indices
        m = 0;
        for(i = 0; i < 256; i++){
            n = mIndex[j][i];
            mIndex[j][i] = m;
            m += n;
        }       
    }
    for(j = 0; j < 4; j++){             // radix sort
        for(i = 0; i < count; i++){     //  sort by current lsb
            u = a[i];
            m = (size_t)(u>>(j<<3))&0xff;
            b[mIndex[j][m]++] = u;
        }
        std::swap(a, b);                //  swap ptrs
    }
    delete[] b;
    return(a);
}

Uma vez que seus valores são inteiros na faixa de 0 ... 1.000.000

Você pode criar uma matriz int de tamanho de 1.000.001, e fazer a coisa toda em dois passes

Init a segunda matriz para todos os zeros.

Faça um passe através de sua matriz de entrada, e usar o valor como um subscrito para incrementar o valor na segunda matriz.

Depois de fazer isso, em seguida, a segunda passagem é fácil. caminhar através da segunda matriz e cada elemento diz-lhe como muitas vezes que número apareceu na matriz original. Use essas informações para repovoar sua matriz de entrada.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top