分治思想在查询中的应用

 分治法是算法设计方法的一种,它通过将问题划分为规模更小的子问题,递归的解决划分后的子问题,再将结果合并从而高效的解决问题。下面通过简单的寻找数组中最大最小值问题,认识到分治思想的优秀之处。

对于寻找数组中最大最小值问题,简单的扫描,需要两遍确定min,max,即复杂度为2*N

奇偶位排序: 经历N/2 次比较,讲较大的数放到奇数位子,较小数放到偶数位置,最后通过N次比较获取min以及max;

int evenfind(int *array, int count) 
{ 
    if(array == NULL) 
        return -1; 
    for(int i =0; i< count; i+=2) 
    { 
        //replace,so the bigger put first 
        if(array[i] > array[i+1]) 
        { 
            int temp = array[i+1]; 
            array[i+1] = array[i]; 
            array[i] = temp; 
        } 
    } 
    int max =0; 
    for(int i=1; i<count; i+=2) 
    { 
        if(max < array[i]) 
            max = array[i]; 
    } 
    return max; 
}


折半查找:分别求出前后N/2个数的min 和 max,然后取较小的min,较大的为max。递归执行过程,先走到可以分的最左边,然后往右边,这样一个最小单元left+right走完,往left+right 的右边拥有同样大小部分,这时把到该部分分为left ,right,完成left+right。依次循环。

比如1,2,3,45,6,7,8 第一次分为 left 1234,right 5,6,7,8. 第二次分为left 1,2 right 3,4; 第三次分为left 1,right 2;

 不可分,比较得到返回2,在比较 left 3,right4,返回4, 再比较left 2和 right 4,返回4,;

然后依次比较5,6返回6,比较7,8返回8;

最后比较4和8 返回8;

int search(int *array, int begin , int end) 
{ 
    if(end - begin <=1) 
    { 
        if(array[end] < array[begin]) 
            return array[begin]; 
        else 
            return array[end]; 
    }
    int maxLeft=0, maxRight=0; 
    maxLeft = search(array, begin, begin + (end - begin) /2); //一直分到最左边,return max
    maxRight = search(array,begin + (end - begin)/2, end); //然后走右边,return max
    if(maxLeft > maxRight) 
        return maxLeft; 
    else 
    { 
        return maxRight; 
    } 
}
关于折半查找复杂度分析如下。

             

              


快速排序:快速排序使用了分治的思想,最坏情况下复杂度为 N*N, 但是平均性能非常好,期望时间复杂度是 n*logn(即对原数列每次分开后形成类似完全二叉树,层数为logn,而每层的比较次数均为n,故为n*logn),另外还可以原址排序。

bool QuickSort(int *array,int begin, int end) 
{ 
    if(begin < end) 
    { 
        //取第一个数据出来,作为比较对照
        int temp = array[begin]; 
        int i = begin; 
        int j = end; 
        while(i < j) 
        { 
            while(i < j && array[j]> temp)  //从尾往前找到第一个大于的值
                j--; 
            if(i<j) 
            { 
                array[i] = array[j];       //把这个值放到之前已经被取出来值的地方i,在j处形成空缺
                i++; 
            } 
            while (i<j && array[i]< temp) //顺序找到第一个小于参考值
                i++; 
            if(i<j) 
            { 
                array[j] = array[i];     //把这个值填到前面形成空缺处 j,i处继续形成空缺
                j--; 
            } 
        } 
        array[i] = temp;   //循环过后,紧接前面i处空缺,填上最开始的参照值
         
        int l = i; 
        //http://blog.csdn.net/morewindows/article/details/6684558 
        QuickSort(array,begin, l-1); 
        QuickSort(array, l+1, end); 
        return true; 
    } 
    else 
    { 
        return false; 
    } 
}

桶排序:桶排序是复杂度 为N,或接近N 排序算法,适合数据分布均匀的排序;思想是分配适当个数的桶,再桶中对数据进行插入排序。桶排序并不是分治思想的应用,但是这种把数据按基数分放到桶中,对桶中数据插入排序,也是分开处理吧。

void doinsertionsortforbucket(int* input, int len) 
{ 
    while( len-- > 0) { 
        if (input[len] > input[len+1]) { 
            int tmp = input[len]; 
            input[len] = input[len+1]; 
            input[len+1] = tmp; 
        } else 
            return; 
    } 
}
void bucketsort(int* input) 
{ 
    queue<int> *buckets[BUCKET_K]; 
    for ( int i = 0; i < BUCKET_K; i++ ) 
        buckets[i] = new queue<int>;
    // Hash the input and insert the content into appropriate bucket based on hash. 
    for (int i=0;i<INPUT_SIZE;i++) 
    { 
        int hashValue = Hash(input[i]); 
        if (hashValue >= BUCKET_K) 
            hashValue = BUCKET_K-1;
        buckets[hashValue]->push(input[i]); 
    }
    // extract the content from each of the buckets in order. 
    // using insertion sort 
    int outputidx = 0; 
    for ( int i = 0; i < BUCKET_K; i++ ) 
    { 
        if (buckets[i]->size() == 1) { 
            input[outputidx++] = buckets[i]->front(); 
            cout << buckets[i]->front() << " | "; 
            buckets[i]->pop(); 
        } 
        if (buckets[i]->size() > 1) 
        { 
            while (!buckets[i]->empty()) 
            { 
                input[outputidx] = buckets[i]->front(); 
                doinsertionsortforbucket(input, outputidx); 
                cout << buckets[i]->front() << " "; 
                buckets[i]->pop(); 
                outputidx++; 
            } 
            cout << "| "; 
        } 
    } 
    // clear buckets. 
    for ( int i = 0; i < BUCKET_K; i++ ) 
        delete buckets[i];
}

总结: 分治思想应用了排序的位置信息,形成线性或树形结构,分开进行比较,不用每次都从头到尾重复某些比较,达到优化时间复杂度的目的。

参考

www.geeksforgeeks.org/bucket-sort-2/

www.sourcetricks.com/2013/03/bucket-sort.html#.VdnXmfmqpBc

blog.sina.com.cn/s/blog_614316190100ei83.html

blog.csdn.net/morewindows/article/details/6684558


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不负初心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值