青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

那誰的技術博客

感興趣領域:高性能服務器編程,存儲,算法,Linux內核
隨筆 - 210, 文章 - 0, 評論 - 1183, 引用 - 0
數據加載中……

[算法]找出m個數中最小的n個數

這個問題屬于常見問題了,我的辦法是采用堆。

截取STL中的partial_sort算法的實現:

template <class RandomAccessIterator, class T, class Compare>
void __partial_sort(RandomAccessIterator first, RandomAccessIterator middle,
                    RandomAccessIterator last, T
*, Compare comp) {
  make_heap(first, middle, comp);
  
for (RandomAccessIterator i = middle; i < last; ++i)
    
if (comp(*i, *first))
      __pop_heap(first, middle, i, T(
*i), comp, distance_type(first));
  sort_heap(first, middle, comp);
}


上面這個函數是對一個序列進行部分排序,排序之后,在first,middle之間的元素有序。
它的做法首先將原始的first,middle中的數據生成一個堆,然后遍歷之后的數據,如果比前面的元素中最大的元素大,就把最小的元素刪除插入這個新的元素,這個過程是lg(middle - first),最后進行堆排序。

不是每個元素都需要重新調整堆,所以最壞的情況時間復雜度是n * lg(middle - first)。

類似的,可以根據這個算法并且使用堆算法解決這個問題,如上所言,最壞的時間復雜度是n * lg(m),其中n是元素總量,m是待查找的最大的m個數。

根據我上面的這個想法, 還有我原來寫過的堆算法,給出解決這個問題的代碼,由于我原來寫的堆算法是大項堆(max-heap),也就是堆中最大的元素在根部,所以這里面求出來的是數中最小的10個數,如果要求最大的10個數,要講這個堆改成小項堆,其實也就是改變堆中父子之間的大小關系罷了,其他的地方不變。

 


/********************************************************************
    created:    2007/3/18
    filename:     main.cpp
    author:        Lichuang
    
    purpose:    測試模擬堆算法
*********************************************************************/

#include <algorithm>
#include <iostream>
#include <time.h>

using namespace std;

// push_heap為向堆中添加一個新的元素, 調用這個算法的前提是[First, Last)之間的元素滿足堆的條件
// 新加入的元素為Last
void    push_heap(int* pFirst, int* pLast);

// pop_heap為從堆中刪除一個元素, 調用這個算法的前提是[First, Last)之間的元素滿足堆的條件
// 被刪除的元素被放置到Last - 1位置,由于這里是max-heap,所以被刪除的元素是這個序列中最大的元素
void    pop_heap(int* pFirst, int* pLast);

// make_heap將序列[First, Last)中的元素按照堆的性質進行重組
void    make_heap(int* pFirst, int* pLast);

// 對堆進行排序, 調用這個函數可以成功排序的前提是[pFirst, pLast)中的元素符合堆的性質
void    sort_heap(int* pFirst, int* pLast);

// 判斷一個序列[First, Last)是否滿足堆的條件,是就返回1,否則返回0
char    is_heap(int* pFirst, int* pLast);

// 用于根據堆的性質調整堆, 將nValue放到位置nHoleIndex, 并且保證堆性質的成立
void    adjust_heap(int *pFirst, int nHoleIndex, int nLen, int nValue);

// 得到一個數組中最小的n個元素
void    get_n_min(int *pArray, int nLen, int n);

void    display_array(int *pArray, int nLength);

int main()
{
    srand(time(NULL));
    int Array[10];
    for(int i = 0; i < 10; ++i)
        Array[i] = rand();

    get_n_min(Array, 10, 2);

    return 0;
}

void get_n_min(int *pArray, int nLen, int n)
{
    int *pTmp = (int*)malloc(sizeof(int) * n);
    if (NULL == pTmp)
    {
        perror("malloc error");
        return;
    }

    int i;
    for (i = 0; i < n; ++i)
        pTmp[i] = pArray[i];
    make_heap(pTmp, pTmp + n);
    display_array(pTmp, n);

    for (; i < nLen; ++i)
    {
        if (pArray[i] < pTmp[0])
             adjust_heap(pTmp, 0, n, pArray[i]);
    }

    // 最后對堆進行排序
    sort_heap(pTmp, pTmp + n);

    cout << "the min n elements of the array is:\n";

    // 打印堆中的數據
    display_array(pTmp, n);

    free(pTmp);
}

// push_heap為向堆中添加一個新的元素, 調用這個算法的前提是[First, Last)之間的元素滿足堆的條件
// 新加入的元素為Last
void push_heap(int* pFirst, int* pLast)
{
    int nTopIndex, nHoleIndex, nParentIndex;
    int nValue;

    nTopIndex = 0;
    nHoleIndex = (int)(pLast - pFirst - 1);
    nParentIndex = (nHoleIndex - 1) / 2;
    nValue = *(pLast - 1);
    // 如果需要插入的節點值比父節點大, 上溯繼續查找
    while (nHoleIndex > nTopIndex && pFirst[nParentIndex] < nValue)
    {
        pFirst[nHoleIndex] = pFirst[nParentIndex];
        nHoleIndex = nParentIndex;
        nParentIndex = (nHoleIndex - 1) / 2;
    }
    pFirst[nHoleIndex] = nValue;
}

// pop_heap為從堆中刪除一個元素, 調用這個算法的前提是[First, Last)之間的元素滿足堆的條件
// 被刪除的元素被放置到Last - 1位置,由于這里是max-heap,所以被刪除的元素是這個序列中最大的元素
void pop_heap(int* pFirst, int* pLast)
{
    int nValue;

    nValue = *(pLast - 1);
    *(pLast - 1) = *pFirst;
    adjust_heap(pFirst, 0, (int)(pLast - pFirst - 1), nValue);
}

// make_heap將序列[First, Last)中的元素按照堆的性質進行重組
void make_heap(int* pFirst, int* pLast)
{
    int nLen, nParentIndex;

    nLen = (int)(pLast - pFirst);
    nParentIndex = (nLen - 1) / 2;

    while (true)
    {
        // 對父節點進行調整, 把父節點的值調整到合適的位置
        adjust_heap(pFirst, nParentIndex, nLen, pFirst[nParentIndex]);
        if (0 == nParentIndex)
            return;
        nParentIndex--;
    }
}

// 對堆進行排序, 調用這個函數可以成功排序的前提是[pFirst, pLast)中的元素符合堆的性質
void sort_heap(int* pFirst, int* pLast)
{
    // 調用pop_heap函數, 不斷的把當前序列中最大的元素放在序列的最后
    while(pLast - pFirst > 1)
        pop_heap(pFirst, pLast--);
}

// 判斷一個序列[First, Last)是否滿足堆的條件,是就返回1,否則返回0
char is_heap(int* pFirst, int* pLast)
{
    int nLen, nParentIndex, nChildIndex;

    nLen = (int)(pLast - pFirst);
    nParentIndex = 0;
    for (nChildIndex = 1; nChildIndex < nLen; ++nChildIndex)
    {
        if (pFirst[nParentIndex] < pFirst[nChildIndex])
            return 0;

        // 當nChildIndex是偶數時, 那么父節點已經和它的兩個子節點進行過比較了
        // 將父節點遞增1
        if ((nChildIndex & 1) == 0)
            ++nParentIndex;
    }

    return 1;
}

// 一個靜態函數僅供adjust_heap調用以證實JJHOU的結論
static void push_heap(int *pFirst, int nHoleIndex, int nTopIndex, int nValue)
{
    int nParentIndex;

    nParentIndex = (nHoleIndex - 1) / 2;
    while (nHoleIndex > nTopIndex && pFirst[nParentIndex] < nValue)
    {
        pFirst[nHoleIndex] = pFirst[nParentIndex];
        nHoleIndex = nParentIndex;
        nParentIndex = (nHoleIndex - 1) / 2;
    }
    pFirst[nHoleIndex] = nValue;
}

// 對堆進行調整, 其中nHoleIndex是目前堆中有空洞的節點索引, nLen是待調整的序列長度
// nValue是需要安插進入堆中的值
void adjust_heap(int *pFirst, int nHoleIndex, int nLen, int nValue)
{
    int nTopIndex, nSecondChildIndex;

    nTopIndex = nHoleIndex;
    nSecondChildIndex = 2 * nTopIndex + 2;
    while (nSecondChildIndex < nLen)
    {
        if (pFirst[nSecondChildIndex] < pFirst[nSecondChildIndex - 1])
            --nSecondChildIndex;
        pFirst[nHoleIndex] = pFirst[nSecondChildIndex];
        nHoleIndex = nSecondChildIndex;
        nSecondChildIndex = 2 * nHoleIndex + 2;
    }
    if (nSecondChildIndex == nLen)
    {
        pFirst[nHoleIndex] = pFirst[nSecondChildIndex - 1];
        nHoleIndex = nSecondChildIndex - 1;
    }

    // 以下兩個操作在這個函數中的作用相同, 證實了<<STL源碼剖析>>中P178中JJHOU所言
    //pFirst[nHoleIndex] = nValue;
    push_heap(pFirst, nHoleIndex, nTopIndex, nValue);
}

void    display_array(int *pArray, int nLength)
{
    for (int i = 0; i < nLength; ++i)
        std::cout << pArray[i] << " ";
    std::cout << std::endl;
}





 

posted on 2007-11-26 18:54 那誰 閱讀(4216) 評論(2)  編輯 收藏 引用 所屬分類: 算法與數據結構

評論

# re: [算法]找出n個中最大的m個數  回復  更多評論   

不錯,我所知道的另外一個算法,也是N*lg(M),似乎這就是最快了的吧。
2007-11-27 13:36 | tangl_99

# re: [算法]找出n個中最大的m個數  回復  更多評論   

只是找10個數而已,不用這么復雜吧,不如直接用有序鏈表算了,構建和維護成本比堆的成本小多了。要是要找的數量偏大,用上堆還差不多。
2007-11-27 16:39 | www.helpsoff.com.cn
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲久久一区二区| 欧美调教vk| 牛牛影视久久网| 中日韩男男gay无套| 一本色道久久综合精品竹菊| 日韩午夜av电影| 中文久久精品| 性娇小13――14欧美| 精品av久久707| 亚洲综合色在线| 亚洲免费在线精品一区| 亚洲伊人一本大道中文字幕| 亚洲——在线| 久久99伊人| 欧美成人精品一区二区| 亚洲日本黄色| 欧美成人午夜激情| 亚洲人成啪啪网站| 亚洲男女自偷自拍图片另类| 国产日韩欧美亚洲一区| 午夜精品久久| 国产精品久久久久影院亚瑟| 欧美一区1区三区3区公司| 一区二区三区四区蜜桃| 欧美一区二区三区久久精品茉莉花| 午夜精品久久久久久久99水蜜桃| 久久国产视频网| 欧美激情视频在线免费观看 欧美视频免费一 | 久久国产99| 欧美激情精品久久久久久| 日韩网站在线| 久久久人人人| 国产精品免费福利| 亚洲三级性片| 久久九九免费视频| 一区二区高清视频| 欧美成人综合一区| 国内一区二区三区在线视频| 亚洲一区二区三区影院| 欧美激情 亚洲a∨综合| 欧美影院精品一区| 国产精品萝li| 亚洲视频观看| 欧美肥婆bbw| 欧美一级在线视频| 国产精品免费看片| 亚洲国产欧美一区二区三区久久| 欧美一区二区视频网站| 一二三四社区欧美黄| 欧美激情亚洲自拍| 亚洲日本中文字幕| 麻豆九一精品爱看视频在线观看免费| 一区二区三区视频免费在线观看| 欧美成人激情在线| 亚洲激情小视频| 欧美不卡一卡二卡免费版| 欧美一级在线播放| 国产热re99久久6国产精品| 亚洲欧美bt| 99在线热播精品免费| 欧美激情一区二区三级高清视频| 精品二区久久| 欧美不卡三区| 蜜月aⅴ免费一区二区三区| 在线观看av一区| 欧美成人一区二免费视频软件| 久久国产加勒比精品无码| 国产麻豆精品久久一二三| 亚洲欧美精品伊人久久| 亚洲神马久久| 国产视频一区二区三区在线观看| 欧美在线网站| 亚洲一本大道在线| 亚洲伊人伊色伊影伊综合网| 夜夜嗨av一区二区三区免费区| 欧美日韩福利在线观看| 中文亚洲视频在线| 亚洲午夜精品网| 国产欧美日韩在线观看| 亚洲一区二区三区色| 亚洲在线观看| 影音先锋另类| 亚洲精品一二区| 国产欧美高清| 欧美大片在线看| 欧美视频网站| 久久久精品国产免大香伊 | 国产精品户外野外| 久久久精品日韩欧美| 牛人盗摄一区二区三区视频| 一区二区三区**美女毛片| 亚洲午夜视频| 尹人成人综合网| 一本色道久久综合亚洲精品婷婷 | 亚洲国产成人精品视频| 亚洲经典三级| 国产日韩精品久久久| 欧美va天堂在线| 国产精品―色哟哟| 欧美 日韩 国产在线| 欧美视频精品一区| 欧美成人精品| 国产欧美日韩综合一区在线播放| 免费欧美日韩| 国产欧美大片| 一本色道精品久久一区二区三区| 国产综合久久久久久鬼色| 亚洲高清视频一区| 国产视频在线观看一区二区| 亚洲国产精品一区二区第四页av | 久久久999精品| 艳女tv在线观看国产一区| 久久电影一区| 亚洲免费视频一区二区| 理论片一区二区在线| 国产日韩视频| 一本久久青青| 亚洲一区二区精品| 欧美久久久久| 欧美激情一区二区久久久| 国产亚洲精品bv在线观看| 亚洲午夜精品福利| 亚洲一区二区三区777| 免费日韩成人| 免费在线欧美黄色| 国模套图日韩精品一区二区| 一区二区免费在线观看| 日韩一级片网址| 欧美一区二区三区四区在线观看| 91久久黄色| 欧美伊人久久| 亚洲一区二区在线| 欧美日韩国产精品一卡| 亚洲国产精品t66y| 亚洲国产精品va| 久久综合中文色婷婷| 每日更新成人在线视频| 国产在线乱码一区二区三区| 亚洲免费在线电影| 欧美一区二区大片| 国产美女精品视频| 午夜精品在线视频| 亚洲一区二区三区免费观看| 欧美日韩直播| 夜夜爽av福利精品导航| 亚洲一卡久久| 国产精品一二三四区| 亚洲欧美久久| 久久视频这里只有精品| 国产真实久久| 久久一区二区精品| 欧美激情国产高清| 99精品福利视频| 国产精品成人观看视频国产奇米| 亚洲图片欧洲图片av| 一区二区三区日韩欧美精品| 欧美三级不卡| 在线亚洲高清视频| 国产一区二区久久久| 亚洲视频二区| 亚洲已满18点击进入久久| 国产精品久久7| 亚洲尤物影院| 久久综合色一综合色88| 91久久线看在观草草青青| 欧美国产日韩一区| 日韩午夜av电影| 性刺激综合网| 1000部国产精品成人观看| 欧美精品自拍偷拍动漫精品| 亚洲午夜激情在线| 毛片精品免费在线观看| 亚洲精品国精品久久99热一| 欧美日韩中国免费专区在线看| 欧美一乱一性一交一视频| 亚洲国产欧美日韩另类综合| 亚洲一区二区三区免费观看 | 在线播放亚洲| 欧美精品aa| 久久国产福利| 91久久午夜| 久久精品国产999大香线蕉| 最新69国产成人精品视频免费| 欧美午夜精品久久久久久人妖| 欧美一区二区三区的| 亚洲人成网站影音先锋播放| 性欧美暴力猛交69hd| 亚洲精品国产精品久久清纯直播 | 亚洲日韩第九十九页| 国产精品―色哟哟| 亚洲美女av黄| 久久婷婷国产麻豆91天堂| 亚洲视频高清| 亚洲七七久久综合桃花剧情介绍| 国产麻豆日韩| 国产精品久久亚洲7777| 欧美精品在线观看一区二区| 蜜臀久久99精品久久久久久9 | 亚洲精品一区二区网址| 久久免费视频网|