基数排序

来源:互联网 发布:ubuntu dd u盘启动盘 编辑:程序博客网 时间:2024/06/05 00:26

今天写了个基数排序的程序,程序现在能运行了,但是里面还有很多地方可以优化,我会再出一个优化的版本的

主要可以优化的地方包含

1. 优化空间,现在需要排序的数据需要再申请一倍的空间用于存储临时数据。如果是一个对于空间要求高的地方,可以优化空间。优化空间,肯定会带来时间上的消耗。怎么优化空间,还没有具体想好,不过也有思路了。

2. 优化时间,现在代码中很多地方的检查其实可以进行剪枝,例如,SortByte函数,这里的循环理论上可以缩减。如果按照数组的大小按照现在是为8的话,可以由原来的8N减到4.5N。现在是按照16进制进行作为一个组,也可以改成256作为组。

 

实验结论:对1亿条数据进行排序测试,使用27s

 

测试程序也给出

main.c

 

#include <stdio.h>

#include <stdlib.h>

#include "RadixSort.h"

#include <time.h> 

 

 

int main(int argc, char **argv)

{

        int iLoop;

        int *iArray;

        //int iSize = 3;

        int iSize = 100000000;

        //int iSize = 50000;

        iArray = (int *) malloc(sizeof(int) * iSize);

        time_t tBegin, tEnd; 

        for(iLoop = 0; iLoop < iSize; iLoop++) {

                iArray[iLoop] = rand();

        }

 

        time(&tBegin); 

        RadixSort(iArray, iSize);

        time(&tEnd); 

 

        for(iLoop = 0; iLoop < iSize; iLoop++) {

                printf("%d/n", iArray[iLoop]);

        }

        printf("%f/n",difftime(tEnd, tBegin));

        return 0;

}

 

 

.h文件RadixSort.h

 

 

 

#ifndef _RADIX_SORT_H_

#define _RADIX_SORT_H_

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

 

 

void RadixSort(int * piArray, int iSize);

 

#endif

 

 

.c文件RadixSort.c

 

 

#include "RadixSort.h"

 

//获取iValue第iByteNum位的数据

static int GetByteValue(int iValue, int iByteNum)

{

    return (iValue >> (4 * iByteNum)) & 0xf;

}

 

#define MAX_SIZE 8

//把iArray进行处理,按照计数排序的第二步处理那样

static void ArrayResort(int iArray[MAX_SIZE][16], int iMaxSize, int iGroupNum, int iSize)

{

    int iLoop, jLoop;

    int iOldValue;

    int iOldTmp;

 

    for(iLoop = 0; iLoop < iMaxSize; iLoop++) {

        iOldValue = iArray[iLoop][iGroupNum - 1];

        //这里从后面往前推,是为了去除那些GetByteValue的结果为0的个数不对的结果

        //现在不存在这个问题,以前是在调用该函数的时候剪枝出现的问题。因为如果要提高速度还要进行剪枝,所以保留这里。

        iArray[iLoop][iGroupNum - 1] = iSize - 1;

        for(jLoop = iGroupNum - 2; jLoop >= 0; jLoop--) {

            iOldTmp = iArray[iLoop][jLoop];

            iArray[iLoop][jLoop] = iArray[iLoop][jLoop + 1] - iOldValue;

            iOldValue = iOldTmp;

        }

    }

}

 

//把iByteInfo里面存储的byte数据,从pFrom复制到pTo里面,pFrom的大小为iSize,比较的是iByteIdx位

static void SortByte(int * pFrom, int *pTo, int iByteInfo[], int iByteIdx, int iSize)

{

    int iLoop;

    int iByteValue;

    //这里使用从后面往前排,是为了不打乱以前排好的那部分数据

    for(iLoop = iSize - 1; iLoop >= 0; iLoop--) {

        iByteValue = GetByteValue(pFrom[iLoop], iByteIdx);

        pTo[iByteInfo[iByteValue]] = pFrom[iLoop];

        iByteInfo[iByteValue]--;

    }

}

 

static void RadixSortPart(int * piArray, int iSize, int *pTmp)

{

    int iArray[MAX_SIZE][16];  //存储基数排序的各个位上面对应值的个数

    int iMaxSize;

    int iTmpSize;

    int *pSaveTmp; //保留哪一个是传进来的tmp

    int *pFrom, *pMid, *pTo;

    int iLoop, jLoop;

 

    iMaxSize = 0; //最大的位数

 

    memset(iArray, 0x00, sizeof(iArray));

 

    for(iLoop = 0; iLoop < iSize; iLoop++) {

        int iTmpValue;

        iTmpSize = 0;

        //从后面往前排的

        for(jLoop = 0; jLoop < MAX_SIZE; jLoop++) {

            iTmpValue = GetByteValue(piArray[iLoop], jLoop);

            iArray[jLoop][iTmpValue]++;

        }

        if(jLoop > iMaxSize) {

            iMaxSize = jLoop;

        }

 

    }

    //数组计数排序累加过程

    ArrayResort(iArray, iMaxSize, 16, iSize);

    pFrom = piArray;

    pTo = pTmp;

    //循环排序,为了节省空间,把原始空间与新申请的空间来源作为from,to使用

    for(iLoop = 0; iLoop < iMaxSize; iLoop++) {

        SortByte(pFrom, pTo, iArray[iLoop], iLoop, iSize);

        pMid = pFrom;

        pFrom = pTo;

        pTo = pMid;

    }

    //如果要最终结果没有存储在piArray中,要不最终的结果放到piArray中

    if(pTo == piArray) {

        for(iLoop = 0; iLoop < iSize; iLoop++) {

            piArray[iLoop] = pTmp[iLoop];

        }

    }

}

 

 

//利用基数排序

void RadixSort(int * piArray, int iSize)

{

        int *pA;

        pA = (int *) malloc(iSize * sizeof(int));

        if(pA == NULL) {

                printf("malloc error:%s %d/n", __FILE__, __LINE__);

                exit(-1);

        }

        RadixSortPart(piArray, iSize, pA);

        free(pA);

}

 

原创粉丝点击