分治思想在查询中的应用

来源:互联网 发布:手机电流检测软件 编辑:程序博客网 时间:2024/04/29 16:49

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

对于寻找数组中最大最小值问题,简单的扫描,需要两遍确定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


0 0