自己写的一个线性复杂度(16n)排序算法用到二叉树和哈希思想,多线程优化和大量数据分块排序都很好弄

本文介绍了一种基于哈希思想的优化排序算法,采用递归方式将数组中的元素按大小分为两个子数组,直至完成排序。该算法的时间复杂度小于O(16n),空间复杂度为O(n)。
作者:王为涛
最近无聊时,就想起来大学想做的个哈希排序算法,就又按哈希的思想做了个优化版的排序算法,请大家指教。
注: 写的时候没有参考其他的排序算法,如果有意外和某些已发表的算法重和的话,还请告知,我做描述修改。

算法步骤:
1. 使用二进制1000 0000 0000 0000 作为第一层的哈希函数,与数组中的数做&操作,将数组分成大数组和小数组,覆盖到原始数组中,并保存各自的开始和结束的下标,供下层递归做循环范围使用。
2. 将哈希函数右移1位,和起止范围送入下一层递归中,重复上步骤的操作,将小数组中再分为一个大数组和小数组,继续递归,直到哈希函数为1或者待递归的范围为1了。
3.递归结束后,原始数组中数字就有序了。

稳定性:
排序时,小数组会从左到右插入数据,可以保持稳定性,大数组从右到左插入数据,如果需要保持稳定性的话,可以将大数组写入原始数组时从右向左遍历插入,可以保持稳定性。
下面的演示程序没有保持稳定性。

算法性能:
算法的时间复杂度是 <O(16n),因为很多大小数组分到最后可能只有一个数了,就不往下分了,会减少递归的层数,递归的层数是根据排序的变量类型和范围决定的,我这里用的0-32760间的数字,所以使用了16位的哈希函数,如果是32位的数字就需要32n的时间复杂度了。
算法的空间复杂度是O(n),使用了n个长度的临时空间做缓存,然后单线程递归时,只保留了16个现场,其中使用的临时变量较少,加上环境压栈所占也很小。同时,可以很容易的将递归操作改成16层的循环操作,可以节省环境压栈所用的空间。

多线程优化:
如果电脑性能较好,多线程能力十分强劲,在第一层递归时,直接使用多线程执行两条分支,这样到最下面一层会产生2的16次方的线程数,很久没用c语言了,线程方面的东西基本忘干净了,了解的网友可以说下。
                if(start<n)
            fun(p,q,start,n,tempn);
        if(m<end)
            fun(p,q,m+1,end,tempn);

大量数据分块排序:
如果数据量十分巨大,可以每次读取一定数据,然后写入硬盘中,然后下次递归重新读取硬盘中的数据,直到满足空间可容纳的时候,可以在内存中进行排序,然后将结果写入硬盘。


[code=c]#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define MAX 1000000

void fun(int *p,int *q,int start,int end , int hashn){
    int n=start;
    int m=end-1;
    int i;
    for(i=start;i<end;i++){
        if((p[i]&hashn) == 0){
            q[n++] = p[i];
        }else {
            q[m--] = p[i];
        }
    }
    for(i=start;i<end;i++){
        p[i]= q[i];
    }
    if(hashn == 1){
        return ;
    } else {
        int tempn = hashn >>1;
        if(start<n)
            fun(p,q,start,n,tempn);
        if(m<end)
            fun(p,q,m+1,end,tempn);
    }
}
void main(){
    unsigned int arr[MAX];
    unsigned int temp[MAX];
    clock_t startt,finish;
    unsigned int hashn = 0x8000;
    srand(time(0));
    int i;
    printf("开始随机生成数组%ld\n",clock());
    for(i=0;i<MAX;i++){
        arr[i]= rand()&32760;
    }
    printf("结束随即生成数组%ld\n",clock());
    startt = clock();
    fun(arr,temp,0,MAX,hashn);
    finish = clock();
    printf("执行时长%f\n",(double)(finish-startt)/CLOCKS_PER_SEC);
}
[/code]

转载请附上此地址
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值