隨筆-199  評(píng)論-203  文章-11  trackbacks-0

          為了便于管理,先引入個(gè)基礎(chǔ)類:

          package algorithms;

          /**

           * @author yovn

           *

           */

          public abstract class Sorter<E 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;

              }

          }

          一 插入排序

          該算法在數(shù)據(jù)規(guī)模小的時(shí)候十分高效,該算法每次插入第K+1到前K個(gè)有序數(shù)組中一個(gè)合適位置,K從0開(kāi)始到N-1,從而完成排序:

          package algorithms;

          /**

           * @author yovn

           */

          public class InsertSorter<E 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;

                    }

              }

                  

              

          }

          二 冒泡排序

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

          package algorithms;

          /**

           * @author yovn

           *

           */

          public class BubbleSorter<E 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);

                  }

              }

              

          }

          三,選擇排序

          選擇排序相對(duì)于冒泡來(lái)說(shuō),它不是每次發(fā)現(xiàn)逆序都交換,而是在找到全局第i小的時(shí)候記下該元素位置,最后跟第i個(gè)元素交換,從而保證數(shù)組最終的有序。

          相對(duì)與插入排序來(lái)說(shuō),選擇排序每次選出的都是全局第i小的,不會(huì)調(diào)整前i個(gè)元素了。

          package algorithms;

          /**

           * @author yovn

           *

           */

          public class SelectSorter<E 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排序可以理解為插入排序的變種,它充分利用了插入排序的兩個(gè)特點(diǎn):

          1)當(dāng)數(shù)據(jù)規(guī)模小的時(shí)候非常高效

          2)當(dāng)給定數(shù)據(jù)已經(jīng)有序時(shí)的時(shí)間代價(jià)為O(N)

          所以,Shell排序每次把數(shù)據(jù)分成若個(gè)小塊,來(lái)使用插入排序,而且之后在這若個(gè)小塊排好序的情況下把它們合成大一點(diǎn)的小塊,繼續(xù)使用插入排序,不停的合并小塊,知道最后成一個(gè)塊,并使用插入排序。

          這里每次分成若干小塊是通過(guò)“增量” 來(lái)控制的,開(kāi)始時(shí)增量交大,接近N/2,從而使得分割出來(lái)接近N/2個(gè)小塊,逐漸的減小“增量“最終到減小到1。

          一直較好的增量序列是2^k-1,2^(k-1)-1,.....7,3,1,這樣可使Shell排序時(shí)間復(fù)雜度達(dá)到O(N^1.5)

          所以我在實(shí)現(xiàn)Shell排序的時(shí)候采用該增量序列

          package algorithms;

          /**

           * @author yovn

           */

          public class ShellSorter<E extends Comparable<E>> extends Sorter<E>  {

              /* (non-Javadoc)

               * Our delta value choose 2^k-1,2^(k-1)-1,常用的冒泡排序 - Werther - 牛昆鵬的博客常用的冒泡排序 - Werther - 牛昆鵬的博客.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)選擇一個(gè)樞紐元素(有很對(duì)選法,我的實(shí)現(xiàn)里采用去中間元素的簡(jiǎn)單方法)

          2)使用該樞紐元素分割數(shù)組,使得比該元素小的元素在它的左邊,比它大的在右邊。并把樞紐元素放在合適的位置。

          3)根據(jù)樞紐元素最后確定的位置,把數(shù)組分成三部分,左邊的,右邊的,樞紐元素自己,對(duì)左邊的,右邊的分別遞歸調(diào)用快速排序算法即可。

          快速排序的核心在于分割算法,也可以說(shuō)是最有技巧的部分。

          package algorithms;

          /**

           * @author yovn

           *

           */

          public class QuickSorter<E 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;

              }

          }

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

          posted on 2009-03-14 08:16 Werther 閱讀(210) 評(píng)論(0)  編輯  收藏

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 望都县| 上高县| 铜陵市| 吉木萨尔县| 松溪县| 金塔县| 平乐县| 丘北县| 濉溪县| 赤壁市| 济南市| 乐安县| 湖口县| 徐水县| 宁夏| 嘉善县| 平湖市| 乌什县| 弥渡县| 大田县| 邵东县| 卢氏县| 曲沃县| 鹤庆县| 湖口县| 思茅市| 颍上县| 禄丰县| 洪洞县| 太康县| 福贡县| 新河县| 远安县| 平塘县| 常山县| 奉贤区| 句容市| 长春市| 北票市| 邯郸市| 元朗区|