• <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>

            那誰的技術(shù)博客

            感興趣領(lǐng)域:高性能服務(wù)器編程,存儲(chǔ),算法,Linux內(nèi)核
            隨筆 - 210, 文章 - 0, 評(píng)論 - 1183, 引用 - 0
            數(shù)據(jù)加載中……

            [算法問題]尋找一個(gè)序列中第n大的元素

            問題描述:給定一個(gè)序列,以及指定這個(gè)序列的一個(gè)范圍,尋找這個(gè)范圍之內(nèi)第n大的元素,如果n大于這個(gè)范圍之內(nèi)的元素?cái)?shù)量那么就返回-1.

            這是快速排序算法中partiton算法的一個(gè)應(yīng)用,不斷的分割序列,如果分割的位置正好是要找的位置,那么返回結(jié)果,否則視情況在前半部分和后半部分繼續(xù)查找,當(dāng)然這個(gè)時(shí)候n值也要相應(yīng)的變化了~~

            /* *******************************************************************
            ????created:????2006/07/04
            ????filename:?????nthElement.cpp
            ????author:????????李創(chuàng)
            ????????????????
            http://www.shnenglu.com/converse/

            ????purpose:????得到一個(gè)序列某個(gè)范圍以內(nèi)的第n個(gè)元素的算法演示
            ????????????????提供了這個(gè)算法的遞歸和非遞歸的實(shí)現(xiàn)算法
            ????????????????同時(shí)為了測試之用提供了堆算法,用于在找到第N個(gè)元素之后
            ????????????????和排序之后的數(shù)組對(duì)應(yīng)位置元素進(jìn)行比較以測試代碼是否正確
            ********************************************************************
            */


            #include?
            < stdio.h >
            #include?
            < stdlib.h >
            #include?
            < time.h >

            // ?交換元素
            void ?Swap( int ? * a,? int ? * b)
            {
            ????
            int ?temp;

            ????temp?
            = ? * a;
            ????
            * a??? = ? * b;
            ????
            * b??? = ?temp;
            }


            // ?打印數(shù)組元素
            void ?DisplayArray( int ?array[],? int ?length)
            {
            ????
            int ?i;

            ????
            for ?(i? = ? 0 ;?i? < ?length;?i ++ )
            ????
            {
            ????????printf(
            " array[%d]?=?%d\n " ,?i,?array[i]);
            ????}

            }


            // ?隨機(jī)創(chuàng)建一個(gè)數(shù)組
            void ?CreateNewArray( int ?array[],? int ?length)
            {
            ????
            for ?( int ?i? = ? 0 ;?i? < ?length;?i ++ )
            ????
            {
            ????????array[i]?
            = ?rand()? % ? 256 ;
            ????}

            }


            // ?對(duì)一個(gè)給定范圍的子序列選定一個(gè)樞紐元素,執(zhí)行完函數(shù)之后返回分割元素所在的位置,
            // ?在分割元素之前的元素都小于樞紐元素,在它后面的元素都大于這個(gè)元素
            int ?Partition( int ?array[],? int ?low,? int ?high)
            {
            ????
            // ?采用子序列的第一個(gè)元素為樞紐元素
            ????
            // ?非常奇怪,如果我把選擇樞紐元素的算法改成注釋掉的那一行那么就會(huì)出錯(cuò)(不是必現(xiàn)的)
            ????
            // ?難道樞紐元素的選擇也會(huì)對(duì)這個(gè)算法產(chǎn)生影響?
            ????
            // ?我在快速排序算法中測試了這個(gè)函數(shù),兩種選擇樞紐元素的算法最后得到的結(jié)果都是正確的~~
            ????
            // int?pivot?=?array[(low?+?high)?/?2];
            ???? int ?pivot? = ?array[low];

            ????
            while ?(low? < ?high)
            ????
            {
            ????????
            // ?從后往前在后半部分中尋找第一個(gè)小于樞紐元素的元素
            ???????? while ?(low? < ?high? && ?array[high]? >= ?pivot)
            ????????
            {
            ????????????
            -- high;
            ????????}


            ????????
            // ?將這個(gè)比樞紐元素小的元素交換到前半部分
            ????????Swap( & array[low],? & array[high]);

            ????????
            // ?從前往后在前半部分中尋找第一個(gè)大于樞紐元素的元素
            ???????? while ?(low? < ?high? && ?array[low]? <= ?pivot)
            ????????
            {
            ????????????
            ++ low;
            ????????}


            ????????
            // ?將這個(gè)比樞紐元素大的元素交換到后半部分
            ????????Swap( & array[low],? & array[high]);
            ????}


            ????
            // ?返回樞紐元素所在的位置
            ???? return ?low;
            }


            // ?尋找數(shù)組array中區(qū)間為[low,?high]中的第n大的元素,
            // ?如果n大于這個(gè)區(qū)間的元素個(gè)數(shù)就返回-1
            // ?非遞歸實(shí)現(xiàn),這個(gè)非遞歸的實(shí)現(xiàn)很是簡單,就是把幾個(gè)出口的遞歸調(diào)用改寫成循環(huán)就好了~~
            int ?nthElement2( int ?array[],? int ?low,? int ?high,? int ?n)
            {
            ????
            if ?(low? > ?high? || ?n? < ? 1 ? || ?n? > ?high? - ?low? + ? 1 )
            ????
            {
            ????????
            return ? - 1 ;
            ????}


            ????
            int ?i;
            ????
            while ?( 1 )
            ????
            {
            ????????i?
            = ?Partition(array,?low,?high);

            ????????
            if ?(low? + ?n? - ? 1 ? == ?i)
            ????????
            {
            ????????????
            return ?array[i];
            ????????}

            ????????
            else ? if ?(low? + ?n? - ? 1 ? < ?i)
            ????????
            {
            ????????????
            // return?nthElement(array,?low,?i?-?1,?n);
            ????????????high? = ?i? - ? 1 ;
            ????????}

            ????????
            else ? if ?(low? + ?n? - ? 1 ? > ?i)
            ????????
            {
            ????????????
            // return?nthElement(array,?i?+?1,?high,?n?-?(i?-?low?+?1));
            ????????????low? = ?i? + ? 1 ;
            ????????????n?
            = ?n? - ?(i? - ?low? + ? 2 );
            ????????}

            ????}

            }


            // ?尋找數(shù)組array中區(qū)間為[low,?high]中的第n大的元素,
            // ?如果n大于這個(gè)區(qū)間的元素個(gè)數(shù)就返回-1
            // ?遞歸實(shí)現(xiàn)
            int ?nthElement( int ?array[],? int ?low,? int ?high,? int ?n)
            {
            ????
            if ?(low? > ?high? || ?n? < ? 1 ? || ?n? > ?high? - ?low? + ? 1 )
            ????
            {
            ????????
            return ? - 1 ;
            ????}


            ????
            int ?i? = ?Partition(array,?low,?high);

            ????
            if ?(low? + ?n? - ? 1 ? == ?i)
            ????
            {
            ????????
            return ?array[i];
            ????}

            ????
            else ? if ?(low? + ?n? - ? 1 ? < ?i)
            ????
            {
            ????????
            return ?nthElement(array,?low,?i? - ? 1 ,?n);
            ????}

            ????
            else ? if ?(low? + ?n? - ? 1 ? > ?i)
            ????
            {
            ????????
            return ?nthElement(array,?i? + ? 1 ,?high,?n? - ?(i? - ?low? + ? 1 ));
            ????}

            }


            // ?調(diào)整堆數(shù)組
            // ?array是待調(diào)整的堆數(shù)組,i是待調(diào)整的數(shù)組元素的位置,length是數(shù)組的長度
            void ?HeapAdjust( int ?array[],? int ?i,? int ?length)
            {
            ????
            int ?child,?temp;

            ????
            for ?(temp? = ?array[i];? 2 ? * ?i? + ? 1 ? < ?length;?i? = ?child)
            ????
            {
            ????????child?
            = ? 2 ? * ?i? + ? 1 ;

            ????????
            // ?得到子結(jié)點(diǎn)中較小的結(jié)點(diǎn)
            ???????? if ?(child? != ?length? - ? 1 ? && ?array[child? + ? 1 ]? > ?array[child])
            ????????????
            ++ child;

            ????????
            // ?如果較小的子結(jié)點(diǎn)大于父結(jié)點(diǎn)那么把較小的子結(jié)點(diǎn)往上移動(dòng),替換它的父結(jié)點(diǎn)
            ???????? if ?(temp? < ?array[child])
            ????????
            {
            ????????????array[i]?
            = ?array[child];
            ????????}

            ????????
            else ???? // ?否則退出循環(huán)
            ???????? {
            ????????????
            break ;
            ????????}

            ????}


            ????
            // ?最后把需要調(diào)整的元素值放到合適的位置
            ????array[i]? = ?temp;
            }

            // ?堆排序算法
            void ?HeapSort( int ?array[],? int ?length)
            {
            ????
            // ?調(diào)整序列的前半部分元素,調(diào)整完之后第一個(gè)元素是序列的最大的元素
            ???? for ?( int ?i? = ?length? / ? 2 ? - ? 1 ;?i? >= ? 0 ;? -- i)
            ????
            {
            ????????HeapAdjust(array,?i,?length);
            ????}


            ????
            // ?從最后一個(gè)元素開始對(duì)序列進(jìn)行調(diào)整,不斷的縮小調(diào)整的范圍直到第一個(gè)元素
            ???? for ?( int ?i? = ?length? - ? 1 ;?i? > ? 0 ;? -- i)
            ????
            {
            ????????
            // ?把第一個(gè)元素和當(dāng)前的最后一個(gè)元素交換,
            ????????
            // ?保證當(dāng)前的最后一個(gè)位置的元素都是在現(xiàn)在的這個(gè)序列之中最大的
            ????????Swap( & array[ 0 ],? & array[i]);

            ????????
            // ?對(duì)當(dāng)前的序列進(jìn)行調(diào)整,調(diào)整完之后保證第一個(gè)元素是當(dāng)前序列的最大值
            ????????HeapAdjust(array,? 0 ,?i);
            ????}

            }


            int ?main( void )
            {
            ????
            int ?array[ 10 ];
            ????srand(time(NULL));

            ????
            int ?n;
            ????printf(
            " input?n:\n " );
            ????scanf(
            " %d " ,? & n);

            ????
            // ?測試遞歸程序
            ????printf( " 測試算法的遞歸函數(shù)實(shí)現(xiàn)\n " );
            ????CreateNewArray(array,?
            10 );
            ????DisplayArray(array,?
            10 );
            ????
            int ?i? = ?nthElement(array,? 0 ,? 9 ,?n);
            ????
            ????HeapSort(array,?
            10 );
            ????printf(
            " after?Heap?Sort:\n " );
            ????DisplayArray(array,?
            10 );

            ????printf(
            " \nfind?%d?=?%d\n " ,?n,?i);
            ????
            if ?(array[n? - ? 1 ]? == ?i)
            ????
            {
            ????????printf(
            " found!!\n " );
            ????}


            ????
            // ?測試非遞歸函數(shù)的實(shí)現(xiàn)
            ????printf( " 測試算法的遞歸函數(shù)實(shí)現(xiàn)\n " );
            ????CreateNewArray(array,?
            10 );
            ????DisplayArray(array,?
            10 );
            ????i?
            = ?nthElement2(array,? 0 ,? 9 ,?n);

            ????HeapSort(array,?
            10 );
            ????printf(
            " after?Heap?Sort:\n " );
            ????DisplayArray(array,?
            10 );

            ????printf(
            " \nfind?%d?=?%d\n " ,?n,?i);
            ????
            if ?(array[n? - ? 1 ]? == ?i)
            ????
            {
            ????????printf(
            " found!!\n " );
            ????}



            ????system(
            " pause " );

            ????
            return ? 0 ;
            }

            posted on 2006-07-08 02:04 那誰 閱讀(3319) 評(píng)論(8)  編輯 收藏 引用 所屬分類: 算法與數(shù)據(jù)結(jié)構(gòu)

            評(píng)論

            # re: [算法問題]尋找一個(gè)序列中第n大的元素  回復(fù)  更多評(píng)論   

            使用STL里面的partial_sort很簡單的就可以得到一個(gè)序列中第N大的元素了。
            2006-07-08 10:29 | 3×7=51

            # re: [算法問題]尋找一個(gè)序列中第n大的元素  回復(fù)  更多評(píng)論   

            犯錯(cuò)誤了,使用STL里面的nth_element才是最好的辦法
            2006-07-08 10:59 | 3×7=51

            # re: [算法問題]尋找一個(gè)序列中第n大的元素  回復(fù)  更多評(píng)論   

            我不否認(rèn)有現(xiàn)成的可以用,但是我更愿意去了解其中的原理~~
            2006-07-08 12:38 | 創(chuàng)系

            # re: [算法問題]尋找一個(gè)序列中第n大的元素  回復(fù)  更多評(píng)論   

            恕我直言,我覺得你這種方法并不是個(gè)好方法。等有時(shí)間我跟你討論一下這個(gè)問題還有什么解決方案。不過你可以去看下stl的實(shí)現(xiàn)(我自己還沒看)。
            2006-07-08 16:55 | 3×7=51

            # re: [算法問題]尋找一個(gè)序列中第n大的元素  回復(fù)  更多評(píng)論   

            贊樓主自己思考問題:)
            2007-03-30 14:40 | wtommy

            # re: [算法問題]尋找一個(gè)序列中第n大的元素  回復(fù)  更多評(píng)論   

            // int pivot = array[(low + high) / 2];
            采用這句的時(shí)候會(huì)出問題,在調(diào)試中發(fā)現(xiàn),當(dāng)pivot本身就是數(shù)組中最大值時(shí),low和high的會(huì)全部循環(huán)完,而跳出循環(huán),沒有實(shí)現(xiàn)交換的目的;
            可能是對(duì)算法理解有問題,不應(yīng)該是low和high進(jìn)行交換,應(yīng)該是是和pivot進(jìn)行交換
            2007-06-18 20:14 | stream

            # re: [算法問題]尋找一個(gè)序列中第n大的元素  回復(fù)  更多評(píng)論   

            我覺得stream說的對(duì),應(yīng)該是和pivot交換。
            2007-12-04 05:08 | alexandercer

            # re: [算法問題]尋找一個(gè)序列中第n大的元素[未登錄]  回復(fù)  更多評(píng)論   

            用紅黑樹數(shù)組,在紅黑樹中的每個(gè)節(jié)點(diǎn)都加入左邊和有邊的節(jié)點(diǎn)的數(shù)目,如果比左節(jié)點(diǎn)數(shù)目大就向左走,比右邊節(jié)點(diǎn)數(shù)目大,就減去這個(gè)數(shù)字再向右走,這樣一直走下去就找到了
            2015-02-01 22:25 | shawn
            久久精品国产99国产电影网| 91精品国产高清久久久久久国产嫩草| 狠狠人妻久久久久久综合蜜桃| 91久久精品视频| 久久精品视频一| 国产综合久久久久久鬼色| 欧美久久综合性欧美| 久久亚洲AV无码西西人体| 四虎影视久久久免费| 久久人人爽爽爽人久久久| 国产高清美女一级a毛片久久w| 怡红院日本一道日本久久 | 久久久久女教师免费一区| 亚洲精品无码久久久| 国产精品一区二区久久精品| 久久天天躁狠狠躁夜夜不卡| 久久不见久久见免费视频7| 久久精品国产精品亚洲人人| 麻豆亚洲AV永久无码精品久久| 久久黄视频| 国产产无码乱码精品久久鸭| 久久综合伊人77777| 国产ww久久久久久久久久| 日韩人妻无码精品久久免费一| 日日狠狠久久偷偷色综合免费| 久久综合久久综合九色| 亚洲国产精品无码久久SM| 久久免费99精品国产自在现线| 欧美精品一本久久男人的天堂| 狠狠综合久久AV一区二区三区| 久久影院午夜理论片无码 | 国内精品久久久久影院网站| 久久久久无码精品国产不卡| 国产精品久久久久久久app| 久久精品成人一区二区三区| 99热精品久久只有精品| 色综合久久中文综合网| 久久99热精品| 久久婷婷久久一区二区三区| 热久久国产精品| 2020最新久久久视精品爱|