zoukankan      html  css  js  c++  java
  • 分治算法

      代码来源于周强老师主讲的,青岛大学,数据结构mooc

      分治法,是把原问题分解成规模较小的问题;从小问题的解,构建出原问题的解使用分治法的前提是,把规模为N的问题划分成两个规模为二分之N的问题,然后把小规模问题再合并起来花的时间是线性时间,T(N) = 2T(N/2) + O(N) --> T(N) = O(N logN)

      在一个数组中查找第K个大的数,使用分治算法

    #include <iostream>
    using namespace std;
    #define maxsize 100
    
    /* 
    8
    8 3 4 1 9 7 10 6 
    3
    */
    
    void swap( int &a, int &b);
    void findKmax(int *a, int left, int right, int k);
    
    int main()
    {
        int a[maxsize];
        int n;
        int k;
        int i;
        
        cout << "input the length of arr:";
        cin >> n;
        
        for(i=0; i<n; ++i)
            cin >> a[i];
        
        cout << "input K:" << endl;
        cin >> k;
        
        findKmax(a, 0, n-1, k );
        
        for(i=0; i<n; ++i)  //调用函数后数组的变化
            cout << a[i] << " ";
        
        cout << "K-th max number is " << a[n-k] << endl;
        
        return 0;
    }
    
    void swap( int &a, int &b){
        int t = a;
        a = b;
        b = t;
    }
    
    void findKmax( int *a, int left, int right, int k ){
        int i=left, j=right, partition = a[i];
        while(i!=j){
            while(i<j && a[j]>partition) j--;
            swap( a[i], a[j] );
            while(i<j && a[i]<partition) i++;
            swap( a[i], a[j] );
            if( right-i+1 == k )  // right-i+1
                return;
            else if( right-i+1 > k )
                findKmax( a, i+1, right, k );
            else if( right-i+1 < k )
                findKmax( a, left, i-1, k-(right-i+1) );
        }
    }
    View Code

      本人认为大数左移更容易理解一些

    #include <iostream> 
    using namespace std;
    #define maxsize 100
    
    int partition(int *l,int low,int high);
    void findk(int k,int *l,int low,int high);
     
    int main() 
    {
        int a[maxsize];
        int m, k;
            
        cin >> m >> k;
        
        for (int i = 0; i < m;i++) {
            cin >> a[i];
        }
        
        findk(k,a,0,m-1);
        
        cout << endl;
        
        for (int i = 0; i < m;i++) {
            cout << a[i] << " ";
        }
        
        return 0;
    } 
     
    int partition(int *l,int low,int high) //大数左移,小数右移
    { 
        int p = l[low];
        while (low != high) {
            while (low < high && l[high] <= p) {
                high--;
            }
            l[low] = l[high];  //大数替换
            while (low < high && l[low] >= p) {
                low++;
            }
            l[high] = l[low]; //小数替换    
        }
        l[low] = p; //p的位置
    
        return low;  // 分界p的下标
    }
    
    void findk(int k,int *l,int low,int high) {
    
        int temp = partition(l,low,high);
    
        if (temp == k - 1) {
            cout << l[temp];
        }
        else if (temp < k-1) { //小于k的位置, 向右边找
            findk(k, l, temp + 1, high);
        }
        else {        //大于k的位置, 向左边找
            findk(k, l, low, temp - 1);        
        }
    } 
    View Code
  • 相关阅读:
    NOIP2009-2018简要题解
    luogu P5023 填数游戏
    Java桌面精灵基础——swing类的使用与关键代码
    c信号处理程序以及setjmp函数longjmp函数的简单应用
    mmapcopy函数的编写
    nm命令的学习以及可执行文件中的段
    关于C中数组和指针的一点理解
    写一个简单的lisp解释器(1)
    House Robber
    SICP_3.31
  • 原文地址:https://www.cnblogs.com/GoldenEllipsis/p/14068960.html
Copyright © 2011-2022 走看看