十大基础排序 · 九 --- 桶排序(不稳定)

1. 分析

/*9.桶排序(BucketSort)
#分析:    
    1. 分桶: 按照最高位分桶,最高位相同按照次高位分桶
    2. 把数据装入对应桶中;(头添加)
    3. 桶内数据排序
    4. 把数据倒回原数组
例子:
    原数组:123653121453110145487663235336571

    桶: 1234561145 110 121 123223533364487 45355716663 653

实现方法:循环
*/

2. 源码

typedef struct bucket
{
    int nValue ;
    struct bucket* pNext;
}Bucket;

void GetMaxMinDropNumber(int arr[] ,int nLength, int* pMax, int* pMin, int* pBase, int* pDropNumber) //423 :NDropBase = 400
{
    int i ;
    int Max = arr[0];
    int Min = arr[0];
    int nDrop = 0;
    int nBase = 1;
    int nMaxIndex = 0;
    int nMinIndex = 0;
    int nTemp = arr[0];

    //get Max, Min
    for(i =0; i< nLength; i++)
    {
        if( Min > arr[i])
            Min = arr[i];
        if(Max < arr[i])
            Max = arr[i];
    }

    //分析数据位数
    while(nTemp)
    {
        nTemp = nTemp/10;
        nBase *=10;
    }//456: nBase = 1000

    while(1)
    {
        nBase /=10;

        nMaxIndex = Max/nBase%10;
        nMinIndex = Min/nBase%10;

        if(nMaxIndex == nMinIndex)
        {
            nDrop = nMaxIndex*nBase;
            Max = Max - nDrop;
            Min = Min - nDrop;
        }
        else
        {
            break;
        }
    }

    *pMax = nMaxIndex;
    *pMin = nMinIndex;
    *pDropNumber = nDrop;
    *pBase = nBase;

    //printf("Max = %d  Min = %d , nDrop = %d \n",nMaxIndex, nMinIndex,nBase, nDrop);
    return ;
}

//桶内冒泡排序
void BucketInnerSort(Bucket* pHead)
{
    //BubbleSort
    Bucket* pMark = pHead;
    Bucket* pTemp = NULL;
    int nTemp; 
    Bucket* pLastUpdatePos;

    while(pMark) //控制遍历次数
    {
        pTemp = pHead;
        pLastUpdatePos = pHead;

        while(pTemp->pNext)
        {
            if(pTemp->nValue < pTemp->pNext->nValue)
            {
                nTemp = pTemp->pNext->nValue;
                pTemp->pNext->nValue = pTemp->nValue;
                pTemp->nValue = nTemp;

                pLastUpdatePos = pTemp->pNext;
            }
            pTemp = pTemp->pNext;
        }
        if(pLastUpdatePos == pHead)
            break;
        pMark = pMark->pNext;
    }   
    return  ;
}

void BucketSort(int *arr, int nLength)
{
    if(arr == NULL ||nLength<=0)
    {
        printf("CountSort :invalid input! \n");
        return ;
    }
    int i;
    int nIndex = 0;
    int nMaxIndex; //最大值最高位(最高位相等,取次高位)
    int nMinIndex;//最小值 最高位(最高位相等,取次高位)
    int nBase;      //返回除数(100)
    int nDropNumber = 0; //若次高位分桶,则 index 需要减去最高位呢;
    Bucket* pTemp = NULL;
    Bucket* pDel = NULL;
    int nTemp;

    GetMaxMinDropNumber(arr, nLength, &nMaxIndex, &nMinIndex,&nBase,  &nDropNumber);

    //1. 来一个哈希表, f分桶
    Bucket* * pBucket = (Bucket**)malloc( sizeof(Bucket*) * (nMaxIndex - nMinIndex + 1) );
    memset(pBucket, 0, sizeof(Bucket*) * (nMaxIndex - nMinIndex+1) );

    //2. 把数据入桶(头添加)
    for (i = 0; i < nLength; i++)
    {
        //若都是4开头,eg:4526则需要按照次高位分桶(4526-4000)/100%10=5;
        nIndex = (arr[i] - nDropNumber)/nBase%10;  

        pTemp = (Bucket*)malloc( sizeof(Bucket));
        pTemp->nValue = arr[i];
        pTemp->pNext = pBucket[nIndex];
        pBucket[nIndex] = pTemp;
    }

    //3. 桶内排序
    for (i = 0; i < nMaxIndex - nMinIndex + 1; i++)
    {
        BucketInnerSort(pBucket[i]);
    }

    //4. 数据倒回原数组    //5. 释放小链表空间
    for (nTemp = 0,i=0; nTemp < nMaxIndex - nMinIndex + 1; nTemp++)
    {
        pTemp = pBucket[nTemp];
        while(pTemp)
        {
            arr[i] = pTemp->nValue;
            pDel = pTemp;

            pTemp = pTemp->pNext;
            i++;

            free(pDel);
            pDel = NULL;
        }
    }

    //5. 释放哈希表空间(桶)
    free(pBucket);
    pBucket = NULL;

}   

void Print(char* pStr, int arr[], int nLength)
{
    printf("%s : ", pStr);
    for(int i=0;i<nLength;i++)
    {
        printf("%d  ",arr[i]);
    }
    printf("\n");
}

int main()
{
    int arr2[] = {4001,4562,4532,4218,4723,4443,4812,4445,4387,4065,4933,4118,4127};

    BucketSort(arr2,sizeof(arr2)/sizeof(arr2[0]));
    Print("Bucket :", arr2,  nLength);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值