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

            那誰(shuí)的技術(shù)博客

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

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

            問(wè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í)為了測(cè)試之用提供了堆算法,用于在找到第N個(gè)元素之后
            ????????????????和排序之后的數(shù)組對(duì)應(yīng)位置元素進(jìn)行比較以測(cè)試代碼是否正確
            ********************************************************************
            */


            #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)生影響?
            ????
            // ?我在快速排序算法中測(cè)試了這個(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)很是簡(jiǎ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ù)組的長(zhǎng)度
            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è)元素開(kāi)始對(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);

            ????
            // ?測(cè)試遞歸程序
            ????printf( " 測(cè)試算法的遞歸函數(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 " );
            ????}


            ????
            // ?測(cè)試非遞歸函數(shù)的實(shí)現(xiàn)
            ????printf( " 測(cè)試算法的遞歸函數(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 那誰(shuí) 閱讀(3314) 評(píng)論(8)  編輯 收藏 引用 所屬分類: 算法與數(shù)據(jù)結(jié)構(gòu)

            評(píng)論

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            用紅黑樹(shù)數(shù)組,在紅黑樹(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久久综合狠狠综合久久止| 欧美亚洲国产精品久久| 久久免费观看视频| 久久亚洲2019中文字幕| 久久黄色视频| 久久久久人妻精品一区三寸蜜桃| 色成年激情久久综合| 亚洲国产精品婷婷久久| 欧美精品一区二区精品久久| 久久综合久久综合久久综合| 久久精品国产亚洲一区二区| 国内精品久久久久久野外| 久久国产精品99久久久久久老狼| 精品一区二区久久久久久久网站| 久久er国产精品免费观看2| 伊人色综合久久天天| 国产精品美女久久久久AV福利| 国产三级观看久久| 久久久WWW免费人成精品| 亚洲人成电影网站久久| 亚洲精品美女久久777777| 久久A级毛片免费观看| 久久精品这里热有精品| 久久精品国产99久久丝袜| 国产精品久久久久久久久软件 | 久久精品国产亚洲精品2020| 99国产精品久久久久久久成人热| 久久国产精品久久久| 精品久久人人做人人爽综合| 久久久久国产精品嫩草影院| 国产精品成人久久久| 久久超乳爆乳中文字幕| 精品国产91久久久久久久a| 99久久这里只精品国产免费| 久久国产精品99精品国产| 久久精品国产72国产精福利| 久久久久久久久久久| 久久九九全国免费| 99久久免费国产精品特黄|