啪啪拉拉噼里啪啦

          初學者天堂資料匯集

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            16 隨筆 :: 73 文章 :: 16 評論 :: 0 Trackbacks

          #

          交換排序的基本思想是:兩兩比較待排序記錄的關鍵字,發現兩個記錄的次序相反時即進行交換,直到沒有反序的記錄為止。
               應用交換排序基本思想的主要排序方法有:冒泡排序和快速排序。

          冒泡排序

          1、排序方法

               將被排序的記錄數組R[1..n]垂直排列,每個記錄R[i]看作是重量為R[i].key的氣泡。根據輕氣泡不能在重氣泡之下的原則,從下往上掃描數組R:凡掃描到違反本原則的輕氣泡,就使其向上"飄浮"。如此反復進行,直到最后任何兩個氣泡都是輕者在上,重者在下為止。
          (1)初始
               R[1..n]為無序區。

          (2)第一趟掃描
               從無序區底部向上依次比較相鄰的兩個氣泡的重量,若發現輕者在下、重者在上,則交換二者的位置。即依次比較(R[n],R[n-1]),(R[n-1],R[n-2]),…,(R[2],R[1]);對于每對氣泡(R[j+1],R[j]),若R[j+1].key<R[j].key,則交換R[j+1]和R[j]的內容。
               第一趟掃描完畢時,"最輕"的氣泡就飄浮到該區間的頂部,即關鍵字最小的記錄被放在最高位置R[1]上。

          (3)第二趟掃描

               掃描R[2..n]。掃描完畢時,"次輕"的氣泡飄浮到R[2]的位置上……
               最后,經過n-1 趟掃描可得到有序區R[1..n]
            注意:
               第i趟掃描時,R[1..i-1]和R[i..n]分別為當前的有序區和無序區。掃描仍是從無序區底部向上直至該區頂部。掃描完畢時,該區中最輕氣泡飄浮到頂部位置R[i]上,結果是R[1..i]變為新的有序區。

          2、冒泡排序過程示例
               對關鍵字序列為49 38 65 97 76 13 27 49的文件進行冒泡排序的過程【參見動畫演示

          3、排序算法
          (1)分析
               因為每一趟排序都使有序區增加了一個氣泡,在經過n-1趟排序之后,有序區中就有n-1個氣泡,而無序區中氣泡的重量總是大于等于有序區中氣泡的重量,所以整個冒泡排序過程至多需要進行n-1趟排序。
               若在某一趟排序中未發現氣泡位置的交換,則說明待排序的無序區中所有氣泡均滿足輕者在上,重者在下的原則,因此,冒泡排序過程可在此趟排序后終止。為此,在下面給出的算法中,引入一個布爾量exchange,在每趟排序開始前,先將其置為FALSE。若排序過程中發生了交換,則將其置為TRUE。各趟排序結束時檢查exchange,若未曾發生過交換則終止算法,不再進行下一趟排序。

          (2)具體算法

            void BubbleSort(SeqList R)
             { //R(l..n)是待排序的文件,采用自下向上掃描,對R做冒泡排序
               int i,j;
               Boolean exchange; //交換標志
               for(i=1;i<n;i++){ //最多做n-1趟排序
                 exchange=FALSE; //本趟排序開始前,交換標志應為假
                 for(j=n-1;j>=i;j--) //對當前無序區R[i..n]自下向上掃描
                  if(R[j+1].key<R[j].key){//交換記錄
                    R[0]=R[j+1]; //R[0]不是哨兵,僅做暫存單元
                    R[j+1]=R[j];
                    R[j]=R[0];
                    exchange=TRUE; //發生了交換,故將交換標志置為真
                   }
                 if(!exchange) //本趟排序未發生交換,提前終止算法
                       return;
               } //endfor(外循環)
              } //BubbleSort
          posted @ 2005-04-01 07:17 噼里啪啦的世界 閱讀(291) | 評論 (0)編輯 收藏

           希爾排序(Shell Sort)是插入排序的一種。因D.L.Shell于1959年提出而得名。

          希爾排序基本思想

            基本思想:
               先取一個小于n的整數d1作為第一個增量,把文件的全部記錄分成d1個組。所有距離為dl的倍數的記錄放在同一個組中。先在各組內進行直接插人排序;然后,取第二個增量d2<d1重復上述的分組和排序,直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有記錄放在同一組中進行直接插入排序為止。
               該方法實質上是一種分組插入方法。

          給定實例的shell排序的排序過程

               假設待排序文件有10個記錄,其關鍵字分別是:
                  49,38,65,97,76,13,27,49,55,04。
               增量序列的取值依次為:
                  5,3,1
               排序過程如【動畫模擬演示】。

          Shell排序的算法實現

          1. 不設監視哨的算法描述

            void ShellPass(SeqList R,int d)
             {//希爾排序中的一趟排序,d為當前增量
               for(i=d+1;i<=n;i++) //將R[d+1..n]分別插入各組當前的有序區
                 if(R[i].key<R[i-d].key){
                   R[0]=R[i];j=i-d; //R[0]只是暫存單元,不是哨兵
                   do {//查找R[i]的插入位置
                      R[j+d];=R[j]; //后移記錄
                      j=j-d; //查找前一記錄
                   }while(j>0&&R[0].key<R[j].key);
                   R[j+d]=R[0]; //插入R[i]到正確的位置上
                 } //endif
             } //ShellPass

            void  ShellSort(SeqList R)
             {
              int increment=n; //增量初值,不妨設n>0
              do {
                    increment=increment/3+1; //求下一增量
                    ShellPass(R,increment); //一趟增量為increment的Shell插入排序
                 }while(increment>1)
              } //ShellSort
            注意:
               當增量d=1時,ShellPass和InsertSort基本一致,只是由于沒有哨兵而在內循環中增加了一個循環判定條件"j>0",以防下標越界。

          2.設監視哨的shell排序算法
               具體算法【參考書目[12] 】

          算法分析

          1.增量序列的選擇

               Shell排序的執行時間依賴于增量序列。
               好的增量序列的共同特征:
            ① 最后一個增量必須為1;
            ② 應該盡量避免序列中的值(尤其是相鄰的值)互為倍數的情況。
               有人通過大量的實驗,給出了目前較好的結果:當n較大時,比較和移動的次數約在nl.25到1.6n1.25之間。

          2.Shell排序的時間性能優于直接插入排序
               希爾排序的時間性能優于直接插入排序的原因:
            ①當文件初態基本有序時直接插入排序所需的比較和移動次數均較少。
            ②當n值較小時,n和n2的差別也較小,即直接插入排序的最好時間復雜度O(n)和最壞時間復雜度0(n2)差別不大。
            ③在希爾排序開始時增量較大,分組較多,每組的記錄數目少,故各組內直接插入較快,后來增量di逐漸縮小,分組數逐漸減少,而各組的記錄數目逐漸增多,但由于已經按di-1作為距離排過序,使文件較接近于有序狀態,所以新的一趟排序過程也較快。
               因此,希爾排序在效率上較直接插人排序有較大的改進。

          3.穩定性
               希爾排序是不穩定的。參見上述實例,該例中兩個相同關鍵字49在排序前后的相對次序發生了變化。
          posted @ 2005-04-01 07:16 噼里啪啦的世界 閱讀(177) | 評論 (0)編輯 收藏

          插入排序(Insertion Sort)的基本思想是:每次將一個待排序的記錄,按其關鍵字大小插入到前面已經排好序的子文件中的適當位置,直到全部記錄插入完成為止。
               本節介紹兩種插入排序方法:直接插入排序和希爾排序。

          直接插入排序基本思想

          1、基本思想

               假設待排序的記錄存放在數組R[1..n]中。初始時,R[1]自成1個有序區,無序區為R[2..n]。從i=2起直至i=n為止,依次將R[i]插入當前的有序區R[1..i-1]中,生成含n個記錄的有序區。

          2、第i-1趟直接插入排序:
               通常將一個記錄R[i](i=2,3,…,n-1)插入到當前的有序區,使得插入后仍保證該區間里的記錄是按關鍵字有序的操作稱第i-1趟直接插入排序。
               排序過程的某一中間時刻,R被劃分成兩個子區間R[1..i-1](已排好序的有序區)和R[i..n](當前未排序的部分,可稱無序區)。
               直接插入排序的基本操作是將當前無序區的第1個記錄R[i]插人到有序區R[1..i-1]中適當的位置上,使R[1..i]變為新的有序區。因為這種方法每次使有序區增加1個記錄,通常稱增量法。
               插入排序與打撲克時整理手上的牌非常類似。摸來的第1張牌無須整理,此后每次從桌上的牌(無序區)中摸最上面的1張并插入左手的牌(有序區)中正確的位置上。為了找到這個正確的位置,須自左向右(或自右向左)將摸來的牌與左手中已有的牌逐一比較。

          一趟直接插入排序方法

          1.簡單方法

               首先在當前有序區R[1..i-1]中查找R[i]的正確插入位置k(1≤k≤i-1);然后將R[k..i-1]中的記錄均后移一個位置,騰出k位置上的空間插入R[i]。
            注意:
               若R[i]的關鍵字大于等于R[1..i-1]中所有記錄的關鍵字,則R[i]就是插入原位置。

          2.改進的方法
            一種查找比較操作和記錄移動操作交替地進行的方法。
          具體做法:
               將待插入記錄R[i]的關鍵字從右向左依次與有序區中記錄R[j](j=i-1,i-2,…,1)的關鍵字進行比較:
               ① 若R[j]的關鍵字大于R[i]的關鍵字,則將R[j]后移一個位置;
                ②若R[j]的關鍵字小于或等于R[i]的關鍵字,則查找過程結束,j+1即為R[i]的插入位置。
               關鍵字比R[i]的關鍵字大的記錄均已后移,所以j+1的位置已經騰空,只要將R[i]直接插入此位置即可完成一趟直接插入排序。

          直接插入排序算法

          1.算法描述

            void lnsertSort(SeqList R)
             { //對順序表R中的記錄R[1..n]按遞增序進行插入排序
              int i,j;
              for(i=2;i<=n;i++) //依次插入R[2],…,R[n]
                if(R[i].key<R[i-1].key){//若R[i].key大于等于有序區中所有的keys,則R[i]
                                        //應在原有位置上
                  R[0]=R[i];j=i-1; //R[0]是哨兵,且是R[i]的副本
                  do{ //從右向左在有序區R[1..i-1]中查找R[i]的插入位置
                   R[j+1]=R[j]; //將關鍵字大于R[i].key的記錄后移
                   j-- ;
                   }while(R[0].key<R[j].key); //當R[i].key≥R[j].key時終止
                  R[j+1]=R[0]; //R[i]插入到正確的位置上
                 }//endif
             }//InsertSort

          posted @ 2005-04-01 07:15 噼里啪啦的世界 閱讀(328) | 評論 (0)編輯 收藏

          1.選擇排序
             選擇排序(Selection Sort)的基本思想是:每一趟從待排序的記錄中選出關鍵字最小的記錄,順序放在已排好序的子文件的最后,直到全部記錄排序完畢。
               常用的選擇排序方法有直接選擇排序和堆排序。

          直接選擇排序(Straight Selection Sort)

          1、直接選擇排序的基本思想

               n個記錄的文件的直接選擇排序可經過n-1趟直接選擇排序得到有序結果:
           ①初始狀態:無序區為R[1..n],有序區為空。
           ②第1趟排序
               在無序區R[1..n]中選出關鍵字最小的記錄R[k],將它與無序區的第1個記錄R[1]交換,使R[1..1]和R[2..n]分別變為記錄個數增加1個的新有序區和記錄個數減少1個的新無序區。
            ……
           ③第i趟排序
            第i趟排序開始時,當前有序區和無序區分別為R[1..i-1]和R[i..n](1≤i≤n-1)。該趟排序從當前無序區中選出關鍵字最小的記錄R[k],將它與無序區的第1個記錄R[i]交換,使R[1..i]和R[i+1..n]分別變為記錄個數增加1個的新有序區和記錄個數減少1個的新無序區。
               這樣,n個記錄的文件的直接選擇排序可經過n-1趟直接選擇排序得到有序結果。

          2、直接選擇排序的過程
            對初始關鍵字為49、38、65、97、76、13、27和49的文件進行直接選擇排序的過程【參見動畫演示

          3、算法描述
            直接選擇排序的具體算法如下:
           void SelectSort(SeqList R)
           {
             int i,j,k;
             for(i=1;i<n;i++){//做第i趟排序(1≤i≤n-1)
               k=i;
               for(j=i+1;j<=n;j++) //在當前無序區R[i..n]中選key最小的記錄R[k]
                 if(R[j].key<R[k].key)
                   k=j; //k記下目前找到的最小關鍵字所在的位置
                 if(k!=i){ //交換R[i]和R[k]
                   R[0]=R[i];R[i]=R[k];R[k]=R[0]; //R[0]作暫存單元
                  } //endif
               } //endfor
            } //SeleetSort

          4、算法分析
          (1)關鍵字比較次數
               無論文件初始狀態如何,在第i趟排序中選出最小關鍵字的記錄,需做n-i次比較,因此,總的比較次數為:
               n(n-1)/2=0(n2)

          (2)記錄的移動次數
               當初始文件為正序時,移動次數為0
               文件初態為反序時,每趟排序均要執行交換操作,總的移動次數取最大值3(n-1)。
               直接選擇排序的平均時間復雜度為O(n2)。

          (3)直接選擇排序是一個就地排序

          (4)穩定性分析
               直接選擇排序是不穩定的

          2.冒泡排序
          3.字符轉換
          posted @ 2005-04-01 07:15 噼里啪啦的世界 閱讀(700) | 評論 (2)編輯 收藏

          1 什么叫作用域?什么叫局部變量?什么叫全局變量?、
          作用域是一個標識符在程序正文中有效的的區域。
          局部變量具有塊作用域的變量
          全局變量具有文件作用域的變量

          變量有那幾種存儲類型

          auto  采用堆棧方式分配內存空間,屬于暫時性存儲,其存儲空間可以被若干變量多次覆蓋使用
          register 存儲類型  存放在寄存器中
          extern  所有程序和函數段都可引用
          static  在內存中固定地址存放 整個程序運行期間都有效。。
          posted @ 2005-04-01 07:08 噼里啪啦的世界 閱讀(124) | 評論 (0)編輯 收藏

          恭喜一下,這是自己的第一個標題....希望大家能夠被接受!
          posted @ 2005-03-31 09:19 噼里啪啦的世界 閱讀(173) | 評論 (0)編輯 收藏

          僅列出標題
          共2頁: 上一頁 1 2 
          主站蜘蛛池模板: 巨野县| 张家界市| 青浦区| 易门县| 康保县| 六安市| 十堰市| 南召县| 英德市| 宣恩县| 岱山县| 澜沧| 收藏| 隆回县| 柳林县| 邻水| 宣城市| 青铜峡市| 秀山| 邵武市| 洛川县| 南宫市| 浏阳市| 大港区| 永丰县| 丰都县| 韩城市| 大同县| 鸡东县| 卢氏县| 十堰市| 连州市| 那曲县| 丹寨县| 达孜县| 台南县| 岫岩| 南川市| 通许县| 达拉特旗| 凌源市|