E81086713E446D36F62B2AA2A3502B5EB155

          Java雜家

          雜七雜八。。。一家之言

          BlogJava 首頁 新隨筆 聯系 聚合 管理
            40 Posts :: 1 Stories :: 174 Comments :: 0 Trackbacks
          為了便于管理,先引入個基礎類:
          package algorithms;

          /**
           * 
          @author yovn
           *
           
          */
          public abstract class Sorter<extends Comparable<E>> {
              
              
          public abstract void sort(E[] array,int from ,int len);
              
              
          public final void sort(E[] array)
              {
                  sort(array,
          0,array.length);
              }
              
          protected final void swap(E[] array,int from ,int to)
              {
                  E tmp
          =array[from];
                  array[from]
          =array[to];
                  array[to]
          =tmp;
              }

          }
          一 插入排序
          該算法在數據規模小的時候十分高效,該算法每次插入第K+1到前K個有序數組中一個合適位置,K從0開始到N-1,從而完成排序:
          package algorithms;
          /**
           * 
          @author yovn
           
          */
          public class InsertSorter<extends Comparable<E>> extends Sorter<E> {

              
          /* (non-Javadoc)
               * @see algorithms.Sorter#sort(E[], int, int)
               
          */
              
          public void sort(E[] array, int from, int len) {
                   E tmp
          =null;
                    
          for(int i=from+1;i<from+len;i++)
                    {
                        tmp
          =array[i];
                        
          int j=i;
                        
          for(;j>from;j--)
                        {
                            
          if(tmp.compareTo(array[j-1])<0)
                            {
                                array[j]
          =array[j-1];
                            }
                            
          else break;
                        }
                        array[j]
          =tmp;
                    }
              }
                  
              

          }

          二 冒泡排序
          這可能是最簡單的排序算法了,算法思想是每次從數組末端開始比較相鄰兩元素,把第i小的冒泡到數組的第i個位置。i從0一直到N-1從而完成排序。(當然也可以從數組開始端開始比較相鄰兩元素,把第i大的冒泡到數組的第N-i個位置。i從0一直到N-1從而完成排序。)

          package algorithms;

          /**
           * 
          @author yovn
           *
           
          */
          public class BubbleSorter<extends Comparable<E>> extends Sorter<E> {

              
          private static  boolean DWON=true;
              
              
          public final void bubble_down(E[] array, int from, int len)
              {
                  
          for(int i=from;i<from+len;i++)
                  {
                      
          for(int j=from+len-1;j>i;j--)
                      {
                          
          if(array[j].compareTo(array[j-1])<0)
                          {
                              swap(array,j
          -1,j);
                          }
                      }
                  }
              }
              
              
          public final void bubble_up(E[] array, int from, int len)
              {
                  
          for(int i=from+len-1;i>=from;i--)
                  {
                      
          for(int j=from;j<i;j++)
                      {
                          
          if(array[j].compareTo(array[j+1])>0)
                          {
                              swap(array,j,j
          +1);
                          }
                      }
                  }
              }
              @Override
              
          public void sort(E[] array, int from, int len) {
                  
                  
          if(DWON)
                  {
                      bubble_down(array,from,len);
                  }
                  
          else
                  {
                      bubble_up(array,from,len);
                  }
              }
              
          }

          三,選擇排序
          選擇排序相對于冒泡來說,它不是每次發現逆序都交換,而是在找到全局第i小的時候記下該元素位置,最后跟第i個元素交換,從而保證數組最終的有序。
          相對與插入排序來說,選擇排序每次選出的都是全局第i小的,不會調整前i個元素了。
          package algorithms;
          /**
           * 
          @author yovn
           *
           
          */
          public class SelectSorter<extends Comparable<E>> extends Sorter<E> {

              
          /* (non-Javadoc)
               * @see algorithms.Sorter#sort(E[], int, int)
               
          */
              @Override
              
          public void sort(E[] array, int from, int len) {
                  
          for(int i=0;i<len;i++)
                  {
                      
          int smallest=i;
                      
          int j=i+from;
                      
          for(;j<from+len;j++)
                      {
                          
          if(array[j].compareTo(array[smallest])<0)
                          {
                              smallest
          =j;
                          }
                      }
                      swap(array,i,smallest);
                             
                  }

              }
           
          }
          四 Shell排序
          Shell排序可以理解為插入排序的變種,它充分利用了插入排序的兩個特點:
          1)當數據規模小的時候非常高效
          2)當給定數據已經有序時的時間代價為O(N)
          所以,Shell排序每次把數據分成若個小塊,來使用插入排序,而且之后在這若個小塊排好序的情況下把它們合成大一點的小塊,繼續使用插入排序,不停的合并小塊,知道最后成一個塊,并使用插入排序。

          這里每次分成若干小塊是通過“增量” 來控制的,開始時增量交大,接近N/2,從而使得分割出來接近N/2個小塊,逐漸的減小“增量“最終到減小到1。

          一直較好的增量序列是2^k-1,2^(k-1)-1,.....7,3,1,這樣可使Shell排序時間復雜度達到O(N^1.5)
          所以我在實現Shell排序的時候采用該增量序列
          package algorithms;

          /**
           * 
          @author yovn
           
          */
          public class ShellSorter<extends Comparable<E>> extends Sorter<E>  {

              
          /* (non-Javadoc)
               * Our delta value choose 2^k-1,2^(k-1)-1,.7,3,1.
               * complexity is O(n^1.5)
               * @see algorithms.Sorter#sort(E[], int, int)
               
          */
              @Override
              
          public void sort(E[] array, int from, int len) {
                  
                  
          //1.calculate  the first delta value;
                  int value=1;
                  
          while((value+1)*2<len)
                  {
                      value
          =(value+1)*2-1;
                  
                  }
              
                  
          for(int delta=value;delta>=1;delta=(delta+1)/2-1)
                  {
                      
          for(int i=0;i<delta;i++)
                      {
                          modify_insert_sort(array,from
          +i,len-i,delta);
                      }
                  }

              }
              
              
          private final  void modify_insert_sort(E[] array, int from, int len,int delta) {
                    
          if(len<=1)return;
                    E tmp
          =null;
                    
          for(int i=from+delta;i<from+len;i+=delta)
                    {
                        tmp
          =array[i];
                        
          int j=i;
                        
          for(;j>from;j-=delta)
                        {
                            
          if(tmp.compareTo(array[j-delta])<0)
                            {
                                array[j]
          =array[j-delta];
                            }
                            
          else break;
                        }
                        array[j]
          =tmp;
                    }

              }
          }

          五 快速排序
          快速排序是目前使用可能最廣泛的排序算法了。
          一般分如下步驟:
          1)選擇一個樞紐元素(有很對選法,我的實現里采用去中間元素的簡單方法)
          2)使用該樞紐元素分割數組,使得比該元素小的元素在它的左邊,比它大的在右邊。并把樞紐元素放在合適的位置。
          3)根據樞紐元素最后確定的位置,把數組分成三部分,左邊的,右邊的,樞紐元素自己,對左邊的,右邊的分別遞歸調用快速排序算法即可。
          快速排序的核心在于分割算法,也可以說是最有技巧的部分。
          package algorithms;

          /**
           * 
          @author yovn
           *
           
          */
          public class QuickSorter<extends Comparable<E>> extends Sorter<E> {

              
          /* (non-Javadoc)
               * @see algorithms.Sorter#sort(E[], int, int)
               
          */
              @Override
              
          public void sort(E[] array, int from, int len) {
                  q_sort(array,from,from
          +len-1);
              }

              
              
          private final void q_sort(E[] array, int from, int to) {
                  
          if(to-from<1)return;
                  
          int pivot=selectPivot(array,from,to);

                  
                  
                  pivot
          =partion(array,from,to,pivot);
                  
                  q_sort(array,from,pivot
          -1);
                  q_sort(array,pivot
          +1,to);
                  
              }


              
          private int partion(E[] array, int from, int to, int pivot) {
                  E tmp
          =array[pivot];
                  array[pivot]
          =array[to];//now to's position is available
                  
                  
          while(from!=to)
                  {
                      
          while(from<to&&array[from].compareTo(tmp)<=0)from++;
                      
          if(from<to)
                      {
                          array[to]
          =array[from];//now from's position is available
                          to--;
                      }
                      
          while(from<to&&array[to].compareTo(tmp)>=0)to--;
                      
          if(from<to)
                      {
                          array[from]
          =array[to];//now to's position is available now 
                          from++;
                      }
                  }
                  array[from]
          =tmp;
                  
          return from;
              }


              
          private int selectPivot(E[] array, int from, int to) {
              
                  
          return (from+to)/2;
              }

          }

          還有歸并排序,堆排序,桶式排序,基數排序,下次在歸納。

          posted on 2007-12-13 01:08 DoubleH 閱讀(36719) 評論(15)  編輯  收藏 所屬分類: Memorandum

          Feedback

          # re: 排序算法復習(Java實現)(一): 插入,冒泡,選擇,Shell,快速排序 2007-12-17 17:23 CoderDream
          不錯,感謝分享,已收藏!  回復  更多評論
            

          # re: 排序算法復習(Java實現)(一): 插入,冒泡,選擇,Shell,快速排序 2008-01-22 09:13 haix
          不錯,感謝分享,已收藏!
          http://www.handandaily.com  回復  更多評論
            

          # re: 排序算法復習(Java實現)(一): 插入,冒泡,選擇,Shell,快速排序 2008-11-12 18:46 first
          很好,都能用  回復  更多評論
            

          # re: 排序算法復習(Java實現)(一): 插入,冒泡,選擇,Shell,快速排序 2008-12-24 14:02 wicker
          學習  回復  更多評論
            

          # re: 排序算法復習(Java實現)(一): 插入,冒泡,選擇,Shell,快速排序[未登錄] 2009-01-14 16:32 小菜鳥
          學到很多,謝謝!  回復  更多評論
            

          # re: 排序算法復習(Java實現)(一): 插入,冒泡,選擇,Shell,快速排序 2009-03-07 19:14 wolfman
          好強大,對JAVA理解真透徹
          不知博主搞了幾年JAVA  回復  更多評論
            

          # re: 排序算法復習(Java實現)(一): 插入,冒泡,選擇,Shell,快速排序 2009-03-11 10:46 costom
          我只看了快速排序,很好很好,但有美中不足,
          在兩個值相等時依然進行交換了。  回復  更多評論
            

          # re: 排序算法復習(Java實現)(一): 插入,冒泡,選擇,Shell,快速排序 2009-03-13 23:09 sss
          非常感謝  回復  更多評論
            

          # re: 排序算法復習(Java實現)(一): 插入,冒泡,選擇,Shell,快速排序 2009-03-22 17:19 rtp
          不太明白.講的不夠詳細..  回復  更多評論
            

          # re: 排序算法復習(Java實現)(一): 插入,冒泡,選擇,Shell,快速排序 2010-06-29 17:36 淘寶
          該算法在數據規模小的時候十分高效,該算法每次插入第K+1到前K個有序數組中一個合適位置,K從0開始到N-1,從而完成排序:  回復  更多評論
            

          # re: 排序算法復習(Java實現)(一): 插入,冒泡,選擇,Shell,快速排序 2010-09-28 16:42 JavaNewFish
          博主你好:
          您寫的快速排序為什么我調用了順序沒有改變啊?我是這樣調用的:
          Integer[] intArray = {1,2,52,6,23,63,27,423,34,56,3,13,23,61};
          QuickSorter<Integer> qs = new QuickSorter<Integer>();
          qs.selectPivot(intArray,0,intArray.length);
          for(int i:intArray){
          System.out.println(i);
          }  回復  更多評論
            

          # re: 排序算法復習(Java實現)(一): 插入,冒泡,選擇,Shell,快速排序[未登錄] 2011-10-31 00:45 ST
          選擇排序有誤,更正如下

          public void sort(E[] array, int from, int len) {
          for(int i=from ;i<len + from;i++)
          {
          int smallest=i;
          int j=i+1;
          for(;j<from+len;j++)
          {
          if(array[j].compareTo(array[smallest])<0)
          {
          smallest=j;
          }
          }
          swap(array,i,smallest);

          }
          }
            回復  更多評論
            

          # re: 排序算法復習(Java實現)(一): 插入,冒泡,選擇,Shell,快速排序[未登錄] 2011-11-04 19:00 helloworld
          @JavaNewFish
          您調錯方法了,應該qs.sort或者q_sort。這也太Fish了吧。  回復  更多評論
            

          # re: 排序算法復習(Java實現)(一): 插入,冒泡,選擇,Shell,快速排序 2012-04-23 19:44 sfsdf
          插入排序中
          for(int i=from+1;i<from+len;i++)
          應該改為
          for(int i=from+1;i<len ;i++)
          有個特殊的需求:
          我若想對一個數組 從 中間from(from>1 from= 2 或 3 什么的 )到末尾來個排序插到從0到from-1個數中且從小到大排序,而從0到from-1個數的排序無所謂的話,樓主這個程序顯然出現下標越界問題 ,這是程序健壯性的問題,當然了,這樣的情況比較少,完全可以不考慮只是改下或許會比較好吧?  回復  更多評論
            

          # re: 排序算法復習(Java實現)(一): 插入,冒泡,選擇,Shell,快速排序 2012-04-23 20:00 sfsdf
          插入排序中
          for(int i=from+1;i<from+len;i++)
          應該改為
          for(int i=from+1;i<len ;i++)
          有個特殊的需求:
          我若想對一個數組 從 中間from(from>1 from= 2 或 3 什么的 )到末尾來個排序且從小到大排序,而從0到from-1個數的排序無所謂的話,樓主這個程序顯然出現下標越界問題 ,這是程序健壯性的問題,當然了,這樣的情況比較少,完全可以不考慮只是改下或許會比較好吧? 回復 更多評論   回復  更多評論
            

          主站蜘蛛池模板: 大庆市| 闸北区| 兴宁市| 马山县| 大英县| 祁门县| 荥阳市| 巴楚县| 交城县| 和顺县| 沙河市| 炉霍县| 璧山县| 光泽县| 南乐县| 枞阳县| 丰镇市| 安泽县| 九寨沟县| 水富县| 蓝田县| 灌阳县| 梅河口市| 车致| 集安市| 罗定市| 河北省| 乌鲁木齐县| 卢湾区| 思茅市| 娄烦县| 乐陵市| 屯门区| 娱乐| 绍兴市| 安化县| 峨眉山市| 隆子县| 洪洞县| 宁晋县| 南投市|