程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> Java-使用二叉樹實現快速排序-遁地龍卷風,java-二叉樹

Java-使用二叉樹實現快速排序-遁地龍卷風,java-二叉樹

編輯:JAVA綜合教程

Java-使用二叉樹實現快速排序-遁地龍卷風,java-二叉樹


(-1)寫在前面

在一次面試中被問及快速排序,回來後又看了一次以前做過的案例,說來慚愧,時至今日還需要讀好長時間,才能明白自己代碼的意思,主要是缺少注釋和圖解,深有感慨,決定好好記錄一下。

之所以使用二叉樹,是因為用遞歸實現當數據量過大時會報棧溢出的錯誤,我試了一下別人的電腦也是這個問題。當然使用二叉樹也會報內存不足,原因是無法創建那麼長的數組,堆區內存溢出。個人感覺要比遞歸實現好的多。

(0)算法詳解

程序隨機產生數據,將其放在數組裡。

a.將最小索引到最大索引之間的數據看做一個整體,程序已最小索引代表的數A為准

b.調換A的位置,使得A左邊是比A大的數,A右邊是比A小的數,此時A的索引被稱為中間索引

c.最小索引到  中間索引-1被看為左孩子 ,中間索引+1 到最大索引被看做右孩子

 

已此圖為例,說明程序流程:

每個節點代表一個數組片段,1是根節點,代表整個數組,每個片段都要經歷a、b的操作

順序為操作1,創建2,3,操作2,創建4,5,操作4,回到2,操作5,回到2,回到1,操作3,創建6,操作6,回到3,回到1,完事。

以下面這個數組為例,說明程序流程

int[] oop = {510, 107,948, 659, 955,438, 283,822};

第一次

a 步驟  最小索引0,最大索引7  A –>510

b步驟  [822, 955, 948, 659, 510, 438, 283, 107]

c  步驟 左孩子0-3  右孩子5-7

第二次

a 步驟  最小索引0,最大索引3  A –>822

b步驟  [948, 955, 822,659]

c  步驟 左孩子0-1  右孩子沒有

第三次

a 步驟  最小索引0,最大索引1  A –>948

b步驟  [955, 948]

c  步驟 左孩子沒有、  右孩子沒有

第四次

a 步驟  最小索引5,最大索引7  A –>438

b步驟[438, 283, 107]

c  步驟 左孩子沒有、, 右孩子6-7

第五次

a 步驟  最小索引6,最大索引7  A –>283

b步驟[283, 107]

c  步驟 左孩子沒有、  右孩子沒有

(2)具體實現

class Test

{

      public static void main(String[] args)

      {

           int len = 8000000;

           int[] oop = new int[len];

           for(int i=0;i<len;i++)

                 oop[i] = (int)(Math.random()*1000);

           Calendar c1 = Calendar.getInstance();

           Sort.quick_sort(oop);

           Calendar c2 = Calendar.getInstance();

           System.out.println(c2.getTimeInMillis()-c1.getTimeInMillis());

      }

}

class Binary

{

      private int left,//最小索引

                      right;//最大索引

      private Binary beforeBinary,//父節點

                         rightBinary,//左孩子

                         leftBinary;//右孩子

      public Binary(int left,int right)

      {

           this.left= left;

           this.right = right;

      }

      public void setLeft(int left)

      {

           this.left = left;

      }

      public void setRight(int right)

      {

           this.right = right;

      }

      public void setBefore(Binary beforeBinary)

      {

           this.beforeBinary = beforeBinary;

      }

      public void setRightBinary(Binary rightBinary)

      {

           this.rightBinary = rightBinary;

      }

      public void setLeftBinary(Binary leftBinary)

      {

            this.leftBinary = leftBinary;

      }

      public int getLeft()

      {

           return this.left;

      }

      public int getRight()

      {

           return this.right;

      }

      public Binary getBeforeBinary()

      {

           return this.beforeBinary;

      }

      public Binary getRightBinary()

      {

           return this.rightBinary;

      }

      public Binary getLeftBinary()

      {

           return this.leftBinary;

      }

}

class Sort

{

      public static void quick_sort(int[] oop)

      {

           Binary headBinary = new Binary(0,oop.length-1),

                    tempBinary  = headBinary;

           int right,

                 left,

                 tempNumber;

           boolean flag = true;

           headBinary.setBefore(null);

           do

           {

                 left = tempBinary.getLeft();

                 right = tempBinary.getRight();

                 tempNumber = oop[left];

                 while(left<right)//結束循環後,tempNumber的左邊是比他大的數,tempNumber的右邊是比他小的數

                 {

                      while(left<right && tempNumber>=oop[right])//從右邊找到比tempNumber大的數

                            right--;

                      if(left<right)

                      {

                            oop[left] = oop[right];//將右邊的數賦值給左邊的

                            left++;//縮減范圍

                      }

                      while(left<right && tempNumber<=oop[left])//從左邊開始找比tempNumber小的數

                            left++;

                      if(left<right)

                       {

                            oop[right] = oop[left];//將左邊的數賦值給右邊

                            right--;//縮減范圍

                      }

                 }

                 //此時left==right

                 oop[left] = tempNumber;

                 if(right<tempBinary.getRight()-1)//創建左孩子

                 {

                      Binary c1 = new Binary(right+1,tempBinary.getRight());

                      tempBinary.setRightBinary(c1);

                      c1.setBefore(tempBinary);

                 }

                 if(left-1>tempBinary.getLeft()) //創建右孩子

                 {

                      Binary c1 = new Binary(tempBinary.getLeft(),left-1);

                      tempBinary.setLeftBinary(c1);

                      c1.setBefore(tempBinary);

                 }

                 flag = true;

                 do//操作A:(遍歷左孩子、右孩子,如果左孩子、右孩子都被遍歷,返回上次節點)重復A操作,直到遍歷到跟節點

                 {

                      if(tempBinary.getLeftBinary() != null)//如果左孩子被創建了,就先遍歷左孩子

                      {

                            Binary c1 = tempBinary.getLeftBinary();;

                            tempBinary.setLeftBinary(null);//最為重要,只要被遍歷的左孩子就將起在上層節點的引用設為null,

                            tempBinary = c1;

                            flag = false;

                      }

                      else if(tempBinary.getRightBinary() != null)//右孩子總是左兄弟節點遍歷後才被遍歷

                      {

                            Binary c1 = tempBinary.getRightBinary();

                            tempBinary.setRightBinary(null);

                            tempBinary = c1;

                            flag = false;

                      }

                      else //左孩子。右孩子都被遍歷返回父節點

                      {

                            if(tempBinary == headBinary) break;

                            tempBinary = tempBinary.getBeforeBinary();

                      }

                 }while(flag);

           }while(tempBinary != headBinary);//當回溯到根節點時,說明排序完畢

      }

}

(3)簡單測試

80000000 內存溢出

8000000 66607ms

800000 1027ms

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved