https://github.com/javanan/DataStructurejava
時間複雜度介紹
空間複雜度介紹
遞歸算法與非遞歸算法區別和轉換
折半查找/二分查找算法
鏈表實現
反轉一個鏈表
直接插入排序
快速排序
選擇排序
冒泡排序
線程與鎖詳解
二叉樹的遍歷
二叉排序樹
圖的詳解
圖的鄰接表存儲構成圖
無向圖的鄰接表存儲-深度優先搜索
無向圖的鄰接表存儲-廣度優先搜索
無向圖的鄰接矩陣存儲-深度優先搜索
無向圖的鄰接矩陣存儲-廣度優先搜索
有向圖的建立
拓撲排序-鄰接矩陣存儲-Kahn算法
拓撲排序-鄰接矩陣存儲-深度優先搜索算法
最短路徑算法之Dijkstra算法(狄克斯特拉算法
ArrayList實現原理
LinkList雙向實現
堆排序
歸併排序
希爾排序
八大排序總結
計數排序
同時找出最大值和最小值最優算法
快速查找法,查找第k個最大的數
10億數據查找前100個
散列表(哈希表)
求最大不重複子串
死鎖
兩個線程交替輸出1010node
關注我,一個仍存夢想的屌絲程序員,天天爲你分享高質量編程博客。python
阿里雲優惠券與阿里雲上雲教程<http://aliyun.guan2ye.com/>linux
package com.wangpos.datastructure.sort; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.TextView; import com.wangpos.datastructure.R; public class TimeComplexityActivity extends AppCompatActivity { private TextView tvIntroduce; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_time_complexity); tvIntroduce = (TextView)findViewById(R.id.introduce); TextView tvTwo = (TextView)findViewById(R.id.tvTwo); tvIntroduce.setText("計算機科學中,算法的時間複雜度是一個函數,它定性描述了該算法的運行時間。" + "這是一個關於表明算法輸入值的字符串的長度的函數。時間複雜度經常使用大O符號表述,不包括這個函數的低階項和首項係數。" + "使用這種方式時,時間複雜度可被稱爲是漸近的,它考察當輸入值大小趨近無窮時的狀況。\n" + "1.通常狀況下,算法中基本操做重複執行的次數是問題規模n的某個函數,用T(n)表示,如有某個輔助函數f(n),使得當n趨近於無窮大時,T(n)/f(n)的極限值爲不等於零的常數,則稱f(n)是T(n)的同數量級函數。記做T(n)=O(f(n)),稱O(f(n)) 爲算法的漸進時間複雜度,簡稱時間複雜度。\n" + "分析:隨着模塊n的增大,算法執行的時間的增加率和 f(n) 的增加率成正比,因此 f(n) 越小,算法的時間複雜度越低,算法的效率越高。\n" + "2. 在計算時間複雜度的時候,先找出算法的基本操做,而後根據相應的各語句肯定它的執行次數,再找出 T(n) 的同數量級(它的同數量級有如下:1,log2n,n,n log2n ,n的平方,n的三次方,2的n次方,n!),找出後,f(n) = 該數量級,若 T(n)/f(n) 求極限可獲得一常數c,則時間複雜度T(n) = O(f(n))" + "\n" + "\n" + "for(i=1; i<=n; ++i) c1 執行 n次\n" + "{\n" + " for(j=1; j<=n; ++j) c2 執行 n平方次\n" + " {\n" + " c[i][j] = 0; c3 //該步驟屬於基本操做執行次數:n的平方次\n" + " for(k=1; k<=n; ++k) c4 執行 n立方次\n" + " c[i][j] += a[i][k] * b[k][j]; c5 //該步驟屬於基本操做執行次數:n的三次方次\n" + " }\n" + "}\n" + "則有T(n)=n^3+n^2 ,根據上面括號裏的同數量級,咱們能夠肯定 n的三次方 爲T(n)的同數量級\n" + "則有f(n)=n^3 ,而後根據 T(n)/f(n) 求極限可獲得常數c\n" + "則該算法的時間複雜度:T(n) = O(n^3) 注:n^3便是n的3次方。" + "" + "" + "上面求解一個算法的時間複雜度過程,假設算法的每一步執行時間c1,c2,c3,執行的次能夠經過計算的n, n,n^2,n^2,n^3 等" + "\n" + "T(n) = c1*n + c2*n^2 + c3*n2 + c4*n^3 + c5*n^3\n" + "找到最高級數 ,去除常數項,就是n^3\n"); tvTwo.setText("" + "一般說的時間複雜度就是,找到這個算法的函數,找到對應的同級數,好比 a*n^2 + b*n +c ,同級數就是n^2,時間複雜度就是n^2\n" + "最好的狀況,就是分析最少次數,好比排序時能夠分析已經有序的 而後從新得出一個方程尋找方程\n" + "最壞的情\n" + "平均的狀況就是一半一半\n"); } }
package com.wangpos.datastructure.sort; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.TextView; import com.wangpos.datastructure.R; public class SpaceComplexityActivity extends AppCompatActivity { private TextView tvIntroduce; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_space_complexity); tvIntroduce = (TextView)findViewById(R.id.introduce); tvIntroduce.setText("空間複雜度(Space Complexity)是對一個算法在運行過程當中臨時佔用存儲空間大小的量度,記作S(n)=O(f(n))。好比直接插入排序的時間複雜度是O(n^2),空間複雜度是O(1) 。而通常的遞歸算法就要有O(n)的空間複雜度了,由於每次遞歸都要存儲返回信息。一個算法的優劣主要從算法的執行時間和所須要佔用的存儲空間兩個方面衡量。" + "\n" + "\n" + "對於一個算法,時間複雜度和空間複雜度每每是相互影響的。當追求一個較好的時間複雜度時,可能會使空間複雜度的性能變差,便可能致使佔用較多的存儲空間;反之,當追求一個較好的空間複雜度時,可能會使時間複雜度的性能變差,便可能致使佔用較長的運行時間。另外,算法的全部性能之間都存在着或多或少的相互影響。所以,當設計一個算法(特別是大型算法)時,要綜合考慮算法的各項性能,算法的使用頻率,算法處理的數據量的大小,算法描述語言的特性,算法運行的機器系統環境等各方面因素,纔可以設計出比較好的算法。算法的時間複雜度和空間複雜度合稱爲算法的複雜度。"); } }
package com.wangpos.datastructure.sort; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.TextView; import com.wangpos.datastructure.R; public class RecursionActivity extends AppCompatActivity { private TextView mTvRecursion; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_recursion); mTvRecursion = (TextView) findViewById(R.id.tvIntroduceRecursion); mTvRecursion.setText("" + " 遞歸算法其實是一種分而治之的方法,它把複雜問題分解爲簡單問題來求解。對於某些複雜問題(例如hanio塔問題)," + "遞歸算法是一種天然且合乎邏輯的解決問題的方式,可是遞歸算法的執行效率一般比較差。所以,在求解某些問題時," + "常採用遞歸算法來分析問題,用非遞歸算法來求解問題;另外,有些程序設計語言不支持遞歸,這就須要把遞歸算法轉換爲非遞歸算法" + "\n" + "\n" + "\n" + " 將遞歸算法轉換爲非遞歸算法有兩種方法,一種是直接求值,不須要回溯;" + "另外一種是不能直接求值,須要回溯。前者使用一些變量保存中間結果," + "稱爲直接轉換法;後者使用棧保存中間結果,稱爲間接轉換法,下面分別討論這兩種方法。" + "" + "" + "\n" + "\n" + "\n" + "1. 直接轉換法\n" + "直接轉換法一般用來消除尾遞歸和單向遞歸,將遞歸結構用循環結構來替代。\n" + "尾遞歸是指在遞歸算法中,遞歸調用語句只有一個,並且是處在算法的最後。例如求階乘的遞歸算法:\n" + "long fact(int n)\n" + "{\n" + " if (n==0) return 1;\n" + " else return n*fact(n-1);\n" + "}\n" + "當遞歸調用返回時,是返回到上一層遞歸調用的下一條語句,而這個返回位置正好是算法的結束處,因此,沒必要利用棧來保存返回信息。對於尾遞歸形式的遞歸算法,能夠利用循環結構來替代。例如求階乘的遞歸算法能夠寫成以下循環結構的非遞歸算法:\n" + "long fact(int n)\n" + "{\n" + " int s=0;\n" + " for (int i=1; i\n" + " s=s*i; //用s保存中間結果\n" + " return s;\n" + "}\n" + "單向遞歸是指遞歸算法中雖然有多處遞歸調用語句,但各遞歸調用語句的參數之間沒有關係,而且這些遞歸調用語句都處在遞歸算法的最後。顯然,尾遞歸是單向遞歸的特例。例如求斐波那契數列的遞歸算法以下:\n" + "int f(int n)\n" + "{\n" + " if (n= =1 | | n= =0) return 1;\n" + " else return f(n-1)+f(n-2);\n" + "}\n" + "對於單向遞歸,能夠設置一些變量保存中間結構,將遞歸結構用循環結構來替代。例如求斐波那契數列的算法中用s1和s2保存中間的計算結果,非遞歸函數以下:\n" + "int f(int n)\n" + "{\n" + " int i, s;\n" + " int s1=1, s2=1;\n" + " for (i=3; i<=n; ++i)\n" + " {\n" + " \ts=s1+s2;\n" + " \ts2=s1; // 保存f(n-2)的值\n" + " \ts1=s; //保存f(n-1)的值\n" + " }\n" + " return s;\n" + "}\n" + "2. 間接轉換法\n" + "該方法使用棧保存中間結果,通常需根據遞歸函數在執行過程當中棧的變化獲得。其通常過程以下:\n" + "將初始狀態s0進棧\n" + "while (棧不爲空)\n" + "{\n" + " 退棧,將棧頂元素賦給s;\n" + " if (s是要找的結果) 返回;\n" + " else \n" + " {\n" + " 尋找到s的相關狀態s1;\n" + " 將s1進棧\n" + " }\n" + "}\n" + "間接轉換法在數據結構中有較多實例,如二叉樹遍歷算法的非遞歸實現、圖的深度優先遍歷算法的非遞歸實現等等" + "" + "\n" + "\n" + "遞歸與迭代的效率比較\n" + "咱們知道,遞歸調用其實是函數本身在調用本身,而函數的調用開銷是很大的,系統要爲每次函數調用分配存儲空間,並將調用點壓棧給予以記錄。" + "而在函數調用結束後,還要釋放空間,彈棧恢復斷點。因此說,函數調用不只浪費空間,還浪費時間。"); TextView tvFeature = (TextView)findViewById(R.id.tvFeature); tvFeature.setText("" + "1.遞歸在解決某些問題的時候使得咱們思考的方式得以簡化,代碼也更加精煉,容易閱讀" + "2.遞歸效率低,系統要爲每次函數調用分配存儲空間,並將調用點壓棧給予以記錄" + "3.小數據量能夠選擇使用"); } }
package com.wangpos.datastructure.sort; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.TextView; import com.wangpos.datastructure.R; public class RecursionActivity extends AppCompatActivity { private TextView mTvRecursion; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_recursion); mTvRecursion = (TextView) findViewById(R.id.tvIntroduceRecursion); mTvRecursion.setText("" + " 遞歸算法其實是一種分而治之的方法,它把複雜問題分解爲簡單問題來求解。對於某些複雜問題(例如hanio塔問題)," + "遞歸算法是一種天然且合乎邏輯的解決問題的方式,可是遞歸算法的執行效率一般比較差。所以,在求解某些問題時," + "常採用遞歸算法來分析問題,用非遞歸算法來求解問題;另外,有些程序設計語言不支持遞歸,這就須要把遞歸算法轉換爲非遞歸算法" + "\n" + "\n" + "\n" + " 將遞歸算法轉換爲非遞歸算法有兩種方法,一種是直接求值,不須要回溯;" + "另外一種是不能直接求值,須要回溯。前者使用一些變量保存中間結果," + "稱爲直接轉換法;後者使用棧保存中間結果,稱爲間接轉換法,下面分別討論這兩種方法。" + "" + "" + "\n" + "\n" + "\n" + "1. 直接轉換法\n" + "直接轉換法一般用來消除尾遞歸和單向遞歸,將遞歸結構用循環結構來替代。\n" + "尾遞歸是指在遞歸算法中,遞歸調用語句只有一個,並且是處在算法的最後。例如求階乘的遞歸算法:\n" + "long fact(int n)\n" + "{\n" + " if (n==0) return 1;\n" + " else return n*fact(n-1);\n" + "}\n" + "當遞歸調用返回時,是返回到上一層遞歸調用的下一條語句,而這個返回位置正好是算法的結束處,因此,沒必要利用棧來保存返回信息。對於尾遞歸形式的遞歸算法,能夠利用循環結構來替代。例如求階乘的遞歸算法能夠寫成以下循環結構的非遞歸算法:\n" + "long fact(int n)\n" + "{\n" + " int s=0;\n" + " for (int i=1; i\n" + " s=s*i; //用s保存中間結果\n" + " return s;\n" + "}\n" + "單向遞歸是指遞歸算法中雖然有多處遞歸調用語句,但各遞歸調用語句的參數之間沒有關係,而且這些遞歸調用語句都處在遞歸算法的最後。顯然,尾遞歸是單向遞歸的特例。例如求斐波那契數列的遞歸算法以下:\n" + "int f(int n)\n" + "{\n" + " if (n= =1 | | n= =0) return 1;\n" + " else return f(n-1)+f(n-2);\n" + "}\n" + "對於單向遞歸,能夠設置一些變量保存中間結構,將遞歸結構用循環結構來替代。例如求斐波那契數列的算法中用s1和s2保存中間的計算結果,非遞歸函數以下:\n" + "int f(int n)\n" + "{\n" + " int i, s;\n" + " int s1=1, s2=1;\n" + " for (i=3; i<=n; ++i)\n" + " {\n" + " \ts=s1+s2;\n" + " \ts2=s1; // 保存f(n-2)的值\n" + " \ts1=s; //保存f(n-1)的值\n" + " }\n" + " return s;\n" + "}\n" + "2. 間接轉換法\n" + "該方法使用棧保存中間結果,通常需根據遞歸函數在執行過程當中棧的變化獲得。其通常過程以下:\n" + "將初始狀態s0進棧\n" + "while (棧不爲空)\n" + "{\n" + " 退棧,將棧頂元素賦給s;\n" + " if (s是要找的結果) 返回;\n" + " else \n" + " {\n" + " 尋找到s的相關狀態s1;\n" + " 將s1進棧\n" + " }\n" + "}\n" + "間接轉換法在數據結構中有較多實例,如二叉樹遍歷算法的非遞歸實現、圖的深度優先遍歷算法的非遞歸實現等等" + "" + "\n" + "\n" + "遞歸與迭代的效率比較\n" + "咱們知道,遞歸調用其實是函數本身在調用本身,而函數的調用開銷是很大的,系統要爲每次函數調用分配存儲空間,並將調用點壓棧給予以記錄。" + "而在函數調用結束後,還要釋放空間,彈棧恢復斷點。因此說,函數調用不只浪費空間,還浪費時間。"); TextView tvFeature = (TextView)findViewById(R.id.tvFeature); tvFeature.setText("" + "1.遞歸在解決某些問題的時候使得咱們思考的方式得以簡化,代碼也更加精煉,容易閱讀" + "2.遞歸效率低,系統要爲每次函數調用分配存儲空間,並將調用點壓棧給予以記錄" + "3.小數據量能夠選擇使用"); } }
package com.wangpos.datastructure.sort; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import com.wangpos.datastructure.R; import thereisnospon.codeview.CodeView; import thereisnospon.codeview.CodeViewTheme; public class EasyLinkListActivity extends AppCompatActivity { private CodeView codeView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_easy_link_list); codeView = (CodeView) findViewById(R.id.codeView); codeView.setTheme(CodeViewTheme.DARK); codeView.showCode("" + " EasyLinkList<Integer> header = new EasyLinkList<>(1);\n" + " EasyLinkList<Integer> second = new EasyLinkList<>(2);\n" + " EasyLinkList<Integer> three = new EasyLinkList<>(3);\n" + "\n" + " header.setNext(second);\n" + " second.setNext(three);\n" + "\n" + " while (header != null) {\n" + " Log.i(\"info\", String.valueOf(header.data));\n" + " header = header.getNext();\n" + " }" + "\n" + " class EasyLinkList<Type> {\n" + "\n" + " private Type data;\n" + " private EasyLinkList<Type> next;\n" + "\n" + " public EasyLinkList(Type dataParam) {\n" + " this.data = dataParam;\n" + " }\n" + "\n" + " public void setNext(EasyLinkList<Type> easyLinkList) {\n" + " this.next = easyLinkList;\n" + " }\n" + "\n" + " public EasyLinkList<Type> getNext() {\n" + " return this.next;\n" + " }\n" + "\n" + " }"); EasyLinkList<Integer> header = new EasyLinkList<>(1); EasyLinkList<Integer> second = new EasyLinkList<>(2); EasyLinkList<Integer> three = new EasyLinkList<>(3); header.setNext(second); second.setNext(three); while (header != null) { Log.i("info", String.valueOf(header.data)); header = header.getNext(); } } class EasyLinkList<Type> { private Type data; private EasyLinkList<Type> next; public EasyLinkList(Type dataParam) { this.data = dataParam; } public void setNext(EasyLinkList<Type> easyLinkList) { this.next = easyLinkList; } public EasyLinkList<Type> getNext() { return this.next; } } }
package com.wangpos.datastructure.sort; import android.support.annotation.NonNull; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import com.wangpos.datastructure.R; import thereisnospon.codeview.CodeView; import thereisnospon.codeview.CodeViewTheme; public class EasyLinkListReverseActivity extends AppCompatActivity implements View.OnClickListener{ private CodeView codeView; private Button btnRun; private EasyLinkList<Integer> header; private TextView tvResult; private TextView tvWeidingxing; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_easy_link_list_reverse); codeView = (CodeView) findViewById(R.id.codeView); btnRun = (Button)findViewById(R.id.btnRun); btnRun.setOnClickListener(this); codeView.setTheme(CodeViewTheme.DARK); tvResult = (TextView) findViewById(R.id.result); // tvWeidingxing = (TextView) findViewById(R.id.tvWendingXing); // // tvWeidingxing.setText(""); codeView.showCode(" public EasyLinkList reverstList(EasyLinkList header) {\n" + "\n" + " /**\n" + " * 保存前一個\n" + " */\n" + " EasyLinkList pre = null;\n" + " /**\n" + " * 保存當前\n" + " */\n" + " EasyLinkList current = header;\n" + "\n" + " while (current != null) { // header 表示當前\n" + "\n" + " EasyLinkList temp = current.getNext();\n" + "\n" + " /**\n" + " * 將當前的next 設置成前一個\n" + " */\n" + " current.setNext(pre);\n" + "\n" + " /**\n" + " * 而後當前的變成了下次的前一個\n" + " */\n" + " pre = current;\n" + "\n" + " /**\n" + " * 下次current 是本次的 temp 也就是下一個\n" + " */\n" + " current = temp;\n" + "\n" + "\n" + " }\n" + "\n" + " /**\n" + " * 這裏current 會複製爲null,因此返回pre\n" + " */\n" + " return pre;\n" + "// return current;\n" + " }"); this.header = new EasyLinkList<>(1); EasyLinkList<Integer> second = new EasyLinkList<>(2); EasyLinkList<Integer> three = new EasyLinkList<>(3); EasyLinkList<Integer> four = new EasyLinkList<>(4); EasyLinkList<Integer> five = new EasyLinkList<>(5); EasyLinkList<Integer> six = new EasyLinkList<>(6); EasyLinkList<Integer> seven = new EasyLinkList<>(7); EasyLinkList<Integer> eight = new EasyLinkList<>(8); EasyLinkList<Integer> nine = new EasyLinkList<>(9); EasyLinkList<Integer> ten = new EasyLinkList<>(10); header.setNext(second); second.setNext(three); three.setNext(four); four.setNext(five); five.setNext(six); six.setNext(seven); seven.setNext(eight); eight.setNext(nine); nine.setNext(ten); } public EasyLinkList reverstList(EasyLinkList header) { /** * 保存前一個 */ EasyLinkList pre = null; /** * 保存當前 */ EasyLinkList current = header; while (current != null) { // header 表示當前 EasyLinkList temp = current.getNext(); /** * 將當前的next 設置成前一個 */ current.setNext(pre); /** * 而後當前的變成了下次的前一個 */ pre = current; /** * 下次current 是本次的 temp 也就是下一個 */ current = temp; } /** * 這裏current 會複製爲null,因此返回pre */ return pre; // return current; } @Override public void onClick(View view) { header = reverstList(header); StringBuilder sb = printString(header); tvResult.setText(sb.toString()); } @NonNull private StringBuilder printString(EasyLinkList<Integer> param) { StringBuilder sb = new StringBuilder(); sb.append("["); EasyLinkList<Integer> header = param; while (header != null) { sb.append(String.valueOf(header.data)); if (header.getNext()!=null) { sb.append(","); } header = header.getNext(); } sb.append("]"); return sb; } class EasyLinkList<Type> { private Type data; private EasyLinkList<Type> next; public EasyLinkList(Type dataParam) { this.data = dataParam; } public void setNext(EasyLinkList<Type> easyLinkList) { this.next = easyLinkList; } public EasyLinkList<Type> getNext() { return this.next; } } }
package com.wangpos.datastructure.sort; import android.support.annotation.NonNull; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; import com.wangpos.datastructure.R; import java.util.Arrays; import thereisnospon.codeview.CodeView; import thereisnospon.codeview.CodeViewTheme; public class DirectInsertSortActivity extends AppCompatActivity implements View.OnClickListener { CodeView codeView; private Button btnRun; private TextView tvData; private TextView tvResult; private TextView tvSummary; private TextView tvTime; int arr[] = {23, 12, 13, 44, 65, 26, 17, 38, 59}; private TextView tvStorage; private DataBean[]dataBeans; private TextView tvWeidingXing; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_direct_insert_sort); codeView = (CodeView) findViewById(R.id.codeView); btnRun = (Button) findViewById(R.id.btnRun); btnRun.setOnClickListener(this); tvData = (TextView) findViewById(R.id.data); tvResult = (TextView) findViewById(R.id.result); tvSummary = (TextView) findViewById(R.id.summary); codeView.setTheme(CodeViewTheme.DARK); tvTime = (TextView) findViewById(R.id.time); tvStorage = (TextView) findViewById(R.id.tvStorage); tvWeidingXing = (TextView) findViewById(R.id.tvWendingXing); tvResult.setText(""); tvData.setText(Arrays.toString(arr)); tvSummary.setText("首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,直接選擇排序而後,再從剩餘未排序元素中繼續尋找最小(大)元素,而後放到已排序序列的末尾。以此類推,直到全部元素均排序完畢"); tvTime.setText("O(N^2)"); tvStorage.setText("O(1)"); tvWeidingXing.setText("穩定"); codeView.showCode(" /**\n" + " * 直接插入排序,從小到大\n" + " *\n" + " * @param arrays 帶排序數組\n" + " * @param <Type> 數組類型\n" + " * @return\n" + " */\n" + " public <Type extends Comparable<? super Type>> Type[] directInsertSort(Type[] arrays) {\n" + " for (int i = 0; i < arrays.length; i++) {\n" + " for (int j = i + 1; j<arrays.length; j++) {\n" + " Type temp = arrays[i];\n" + " if (arrays[j].compareTo(arrays[i]) < 0) {//從小到大\n" + " arrays[i] = arrays[j];\n" + " arrays[j] = temp;\n" + " }\n" + "\n" + " }\n" + " }\n" + "\n" + " return arrays;\n" + " }"); dataBeans = new DataBean[arr.length]; for (int i = 0; i < arr.length; i++) { dataBeans[i] = new DataBean(arr[i]); } } @Override public void onClick(View view) { DataBean arrays[] = directInsertSort(dataBeans); tvResult.setText(Arrays.toString(arrays)); } /** * 直接插入排序,從小到大 * * @param arrays 帶排序數組 * @param <Type> 數組類型 * @return */ public <Type extends Comparable<? super Type>> Type[] directInsertSort(Type[] arrays) { for (int i = 0; i < arrays.length; i++) { for (int j = i ; j>=0; j--) { Type temp = arrays[i]; if (arrays[j].compareTo(arrays[i]) < 0) {//從小到大 arrays[i] = arrays[j]; arrays[j] = temp; } } } return arrays; } public class DataBean implements Comparable { private int data; public DataBean(int datap) { this.data = datap; } @Override public int compareTo(@NonNull Object o) { DataBean target = (DataBean) o; if (data > target.data) { return 1; } else if (data < target.data) { return -1; } else { return 0; } } @Override public String toString() { return String.valueOf(data); } } }
package com.wangpos.datastructure.sort; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import com.wangpos.datastructure.R; import android.support.annotation.NonNull; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import com.wangpos.datastructure.R; import com.wangpos.datastructure.core.BaseActivity; import com.wangpos.datastructure.core.CodeBean; import java.util.Arrays; import thereisnospon.codeview.CodeView; import thereisnospon.codeview.CodeViewTheme; public class QuickSortActivity extends BaseActivity { int arr[] = {23, 12, 13, 44, 65, 26, 17, 38, 59}; /** * 記錄一個23,讓出本身位置,將小得放進來 * * 23, 12, 13, 44, 65, 26, 17, 38, 59 * * 17, 12, 13, 44, 65, 26, 17, 38, 59 * * 17, 12, 13, 44, 65, 26, 44, 38, 59 * * 一趟之後得 17, 12, 13, 23, 65, 26, 44, 38, 59 * * 一趟=[17, 12, 13, 44, 65, 26, 44, 38, 59] I/info (27284): 一趟=[17, 12, 13, 44, 65, 26, 44, 38, 59] I/info (27284): 一趟=[13, 12, 13, 23, 65, 26, 44, 38, 59] I/info (27284): 一趟=[12, 12, 17, 23, 65, 26, 44, 38, 59] I/info (27284): 一趟=[12, 13, 17, 23, 59, 26, 44, 38, 59] I/info (27284): 一趟=[12, 13, 17, 23, 38, 26, 44, 38, 65] I/info (27284): 一趟=[12, 13, 17, 23, 26, 26, 44, 59, 65] */ @Override protected void initData() { setTitleText("快速排序"); addItem(new CodeBean("快速排序",quickSortCode)); } @Override protected String getTextData() { return Arrays.toString(arr); } @Override protected int getImageData() { return 0; } @Override protected String getResultData() { sort(arr,0,arr.length-1); return Arrays.toString(arr); } @Override protected String getTimeData() { return "O(nlogn)"; } @Override protected String getSpaceTimeData() { return ""; } @Override protected String getWendingXingData() { return "不穩定"; } @Override protected String getSummaryData() { return "快速排序(Quicksort)是對冒泡排序的一種改進。\n" + "快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:經過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的全部數據都比另一部分的全部數據都要小" + ",而後再按此方法對這兩部分數據分別進行快速排序,整個排序過程能夠遞歸進行,以此達到整個數據變成有序序列。"; } private static int sortUnit(int[] array, int low, int high) { int key = array[low];//選取第一個爲基準數 while (low < high) { /*從後向前搜索比key小的值*/ while (array[high] >= key && high > low) --high; /*比key小的放左邊*/ array[low] = array[high]; /*從前向後搜索比key大的值,比key大的放右邊*/ while (array[low] <= key && high > low) ++low; /*比key大的放右邊*/ array[high] = array[low];// /** * 一次的效果就是比Key小的放在了key(low)位置,再找比key大的放在high位置 */ Log.i("info","一趟="+Arrays.toString(array)); // Log.i("info","一趟="+"low="+low +"high="+high); } /*左邊都比key小,右邊都比key大。//將key放在遊標當前位置。 //此時low等於high */ /** * 相遇位置, * 一開始meetPosition 等於low */ int meetPosition = low = high; /** * key的位置被霸佔了,因此key的位置是最終相遇的位置 */ array[meetPosition] = key; return meetPosition; } /**快速排序 *@paramarry *@return */ public static void sort(int[] array, int low, int high) { if (low >= high) return; /*完成一次單元排序*/ int index = sortUnit(array, low, high); /*對左邊單元進行排序*/ sort(array, low, index - 1); // /*對右邊單元進行排序*/ sort(array, index + 1, high); } private static String quickSortCode = "private static int sortUnit(int[] array, int low, int high)\n" + " {\n" + " int key = array[low];//選取第一個爲基準數\n" + "\n" + " while (low < high)\n" + " {\n" + " /*從後向前搜索比key小的值*/\n" + " while (array[high] >= key && high > low)\n" + " --high;\n" + " /*比key小的放左邊*/\n" + " array[low] = array[high];\n" + " /*從前向後搜索比key大的值,比key大的放右邊*/\n" + " while (array[low] <= key && high > low)\n" + " ++low;\n" + " /*比key大的放右邊*/\n" + " array[high] = array[low];//\n" + "\n" + "\n" + " /**\n" + " * 一次的效果就是比Key小的放在了key(low)位置,再找比key大的放在high位置\n" + " */\n" + "\n" + "\n" + " Log.i(\"info\",\"一趟=\"+Arrays.toString(array));\n" + "// Log.i(\"info\",\"一趟=\"+\"low=\"+low +\"high=\"+high);\n" + " }\n" + " /*左邊都比key小,右邊都比key大。//將key放在遊標當前位置。\n" + " //此時low等於high */\n" + " /**\n" + " * 相遇位置,\n" + " * 一開始meetPosition 等於low\n" + " */\n" + " int meetPosition = low = high;\n" + "\n" + " /**\n" + " * key的位置被霸佔了,因此key的位置是最終相遇的位置\n" + " */\n" + " array[meetPosition] = key;\n" + "\n" + " return meetPosition;\n" + " }\n" + " /**快速排序\n" + " *@paramarry\n" + " *@return */\n" + " public static void sort(int[] array, int low, int high)\n" + " {\n" + " if (low >= high)\n" + " return;\n" + " /*完成一次單元排序*/\n" + " int index = sortUnit(array, low, high);\n" + " /*對左邊單元進行排序*/\n" + " sort(array, low, index - 1);\n" + "// /*對右邊單元進行排序*/\n" + " sort(array, index + 1, high);\n" + " }"; }
package com.wangpos.datastructure.sort; import com.wangpos.datastructure.core.BaseActivity; import com.wangpos.datastructure.core.CodeBean; import java.util.Arrays; /** * Created by qiyue on 2017/11/21. */ public class OptionSortActivity extends BaseActivity { int arr[] = {23, 12, 13, 44, 65, 26, 17, 38, 59}; @Override protected void initData() { setTitleText("選擇排序"); addItem(new CodeBean("選擇排序",selectSortStr)); } @Override protected String getTextData() { return Arrays.toString(arr); } @Override protected int getImageData() { return 0; } @Override protected String getResultData() { return Arrays.toString(selectSort(arr)); } @Override protected String getTimeData() { return "O(n^2)"; } @Override protected String getSpaceTimeData() { return "O(1)"; } @Override protected String getWendingXingData() { return "穩定"; } @Override protected String getSummaryData() { return "每一趟從待排序的記錄中選出最小的元素,順序放在已排好序的序列最後,直到所有記錄排序完畢,此排序就是對冒泡的優化,沒必要每次都進行交換"; } private static final String selectSortStr = "public void selectSort(int arr[]){\n" + " for(int i = 0; i < arr.length - 1; i++) {// 作第i趟排序\n" + " int k = i;\n" + " for(int j = k + 1; j < arr.length; j++){// 選最小的記錄\n" + " if(arr[j] < arr[k]){\n" + " k = j; //記下目前找到的最小值所在的位置\n" + " }\n" + " }\n" + " //在內層循環結束,也就是找到本輪循環的最小的數之後,再進行交換\n" + " if(i != k){ //交換a[i]和a[k]\n" + " int temp = arr[i];\n" + " arr[i] = arr[k];\n" + " arr[k] = temp;\n" + " }\n" + " }\n" + " }"; public int[] selectSort(int arr[]){ for(int i = 0; i < arr.length - 1; i++) {// 作第i趟排序 int k = i; for(int j = k + 1; j < arr.length; j++){// 選最小的記錄 if(arr[j] < arr[k]){ k = j; //記下目前找到的最小值所在的位置 } } //在內層循環結束,也就是找到本輪循環的最小的數之後,再進行交換 if(i != k){ //交換a[i]和a[k] int temp = arr[i]; arr[i] = arr[k]; arr[k] = temp; } } return arr; } }
package com.wangpos.datastructure.sort; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import com.wangpos.datastructure.R; import com.wangpos.datastructure.core.BaseActivity; import com.wangpos.datastructure.core.CodeBean; import java.lang.reflect.Array; import java.util.Arrays; public class BubbleSortActivity extends BaseActivity { int arr[] = {23, 12, 13, 44, 65, 26, 17, 38, 59}; @Override protected void initData() { setTitleText("冒泡排序"); addItem(new CodeBean("冒泡排序",bubbleSortStr)); } @Override protected String getTextData() { return Arrays.toString(arr); } @Override protected int getImageData() { return 0; } @Override protected String getResultData() { return Arrays.toString(bubbleSort(arr)); } @Override protected String getTimeData() { return "O(n^2)"; } @Override protected String getSpaceTimeData() { return "O(1)"; } @Override protected String getWendingXingData() { return "穩定"; } @Override protected String getSummaryData() { return "一次比較兩個元素,若是他們的順序錯誤就把他們交換過來。" + "走訪數列的工做是重複地進行直到沒有再須要交換,也就是說該數列已經排序完成"; } private static final String bubbleSortStr = "public void bubbleSort(int[] a)\n" + " {\n" + " int temp = 0;\n" + " /**這裏的i表示比較多少次,第一次要所有進行比較得出最大的一個,第二次應該除去最大的一個,比較剩下的*/\n" + " for (int i = a.length - 1; i > 0; --i)\n" + " {\n" + " for (int j = 0; j < i; ++j)\n" + " {\n" + " if (a[j + 1] < a[j])\n" + " {\n" + " temp = a[j];\n" + " a[j] = a[j + 1];\n" + " a[j + 1] = temp;\n" + " }\n" + " }\n" + " }\n" + " }"; public int[] bubbleSort(int[] a) { int temp = 0; /**這裏的i表示比較多少次,第一次要所有進行比較得出最大的一個,第二次應該除去最大的一個,比較剩下的*/ for (int i = a.length - 1; i > 0; --i) { for (int j = 0; j < i; ++j) { if (a[j + 1] < a[j]) { temp = a[j]; a[j] = a[j + 1]; a[j + 1] = temp; } } } return a; } }
package com.wangpos.datastructure.java; /** * Created by qiyue on 2017/11/17. */ import android.os.Bundle; import android.os.Handler; import android.support.annotation.NonNull; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import com.wangpos.datastructure.R; import java.util.Arrays; import thereisnospon.codeview.CodeView; import android.support.annotation.NonNull; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; import com.wangpos.datastructure.R; import java.util.Arrays; import thereisnospon.codeview.CodeView; import thereisnospon.codeview.CodeViewTheme; public class JavaThreadActivity extends AppCompatActivity implements View.OnClickListener { CodeView codeView; private Button btnRun; private TextView tvData; private TextView tvResult; private TextView tvSummary; private TextView tvTime; int arr[] = {23, 12, 13, 44, 65, 26, 17, 38, 59}; private TextView tvStorage; private com.wangpos.datastructure.sort.DirectInsertSortActivity.DataBean[] dataBeans; private TextView tvWeidingXing; private static TextView tvPrintField; static Handler mHandler = new Handler(); private CodeView codeView2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.java_thread_activity); codeView = (CodeView) findViewById(R.id.codeView); tvData = (TextView) findViewById(R.id.data); tvResult = (TextView) findViewById(R.id.result); codeView.setTheme(CodeViewTheme.DARK); codeView2 = (CodeView) findViewById(R.id.codeView2); codeView2.setTheme(CodeViewTheme.DARK); tvPrintField = (TextView) findViewById(R.id.printText); tvData.setText("" + "1.單例對象的同步方法,原理就是使用同一把鎖\n" + "2.輪訓條件發\n" + "3.wait/notify機制\n" + "4.是利用CyclicBarrierAPI\n" + "5.管道通訊就是使用java.io.PipedInputStream\n" + "6.利用Lock和Condition\n" + "7.利用volatile\n" + "8.利用AtomicInteger\n" + "分佈式系統中說的兩種通訊機制:共享內存機制和消息通訊機制"); tvResult.setText("類鎖,對象鎖\n" + "\n" + "1.對象鎖:java的全部對象都含有1個互斥鎖,這個鎖由JVM自動獲取和釋放。線程進入synchronized方法的時候獲取該對象的鎖," + "固然若是已經有線程獲取了這個對象的鎖,那麼當前線程會等待;synchronized方法正常返回或者拋異常而終止," + "JVM會自動釋放對象鎖。這裏也體現了用synchronized來加鎖的1個好處,方法拋異常的時候,鎖仍然能夠由JVM來自動釋放。\n" + "\n\n" + "2.類鎖:對象鎖是用來控制實例方法之間的同步,類鎖是用來控制靜態方法(或靜態變量互斥體)之間的同步。其實類鎖只是一個概念上的東西," + "並非真實存在的,它只是用來幫助咱們理解鎖定實例方法和靜態方法的區別的。咱們都知道,java類可能會有不少個對象,可是隻有1個Class對象," + "也就是說類的不一樣實例之間共享該類的Class對象。Class對象其實也僅僅是1個java對象,只不過有點特殊而已。因爲每一個java對象都有1個互斥鎖" + ",而類的靜態方法是須要Class對象。因此所謂的類鎖,不過是Class對象的鎖而已。獲取類的Class對象有好幾種,最簡單的就是MyClass.class的方式。\n" + "\n" + "\n" + "\n"); codeView.showCode(" /**\n" + " * 類鎖實現一:使用 static synchronized\n" + " * 建立兩個線程,每一個線程從1打印到10000 ,運行結果,t1先打印完後,t2 再打印\n" + " * 使用類鎖,無論建立多少個線程,他們都使用的是同一把鎖,由於Java無論建立多少個對象,Class對象始終一個\n" + " *\n" + " */\n" + " TestThread t1 = new TestThread(1);\n" + " TestThread t2 = new TestThread(2);\n" + " t1.start();\n" + " t2.start();" + "\n" + "\n" + " public static class TestThread extends Thread{\n" + "\n" + " private int number;\n" + "\n" + " public TestThread(int number){\n" + " this.number = number;\n" + " }\n" + "\n" + " @Override\n" + " public void run() {\n" + " super.run();\n" + " test(number);\n" + "\n" + " }\n" + " //類鎖實現之一\n" + " private static synchronized void test(final int number) {\n" + " for (int i=0;i<10000;i++) {\n" + "\n" + " Log.i(\"info\", \"number=\" + number +\"say=\"+ i);\n" + " }\n" + " }\n" + " }" + "" + "\n" + "\n" + "" + " /**\n" + " * 類鎖實現二:使用 synchronized(TestThread.class){}\n" + " */\n" + " TestThread t1 = new TestThread(1);\n" + " TestThread t2 = new TestThread(2);\n" + " t1.start();\n" + " t2.start();" + "\n" + "\n" + "\n" + " public static class TestThread extends Thread {\n" + "\n" + " private int number;\n" + "\n" + " public TestThread(int number) {\n" + " this.number = number;\n" + " }\n" + "\n" + " @Override\n" + " public void run() {\n" + " super.run();\n" + " test(number);\n" + "\n" + " }\n" + "// //類鎖實現之一\n" + "// private static synchronized void test(final int number) {\n" + "// for (int i=0;i<10000;i++) {\n" + "//\n" + "// Log.i(\"info\", \"number=\" + number +\"say=\"+ i);\n" + "// }\n" + "// }\n" + "\n" + " private void test(int number) {\n" + " synchronized (TestThread.class) {\n" + " for (int i = 0; i < 10000; i++) {\n" + " Log.i(\"info\", \"number=\" + number + \"say=\" + i);\n" + " }\n" + " }\n" + " }\n" + " }"); /** * 類鎖實現一:使用 static synchronized * 建立兩個線程,每一個線程從1打印到10000 ,運行結果,t1先打印完後,t2 再打印 * 使用類鎖,無論建立多少個線程,他們都使用的是同一把鎖,由於Java無論建立多少個對象,Class對象始終一個 * */ // TestThread t1 = new TestThread(1); // TestThread t2 = new TestThread(2); // t1.start(); // t2.start(); /** * 類鎖實現二:使用 synchronized(TestThread.class){} */ // TestThread t1 = new TestThread(1); // TestThread t2 = new TestThread(2); // t1.start(); // t2.start(); codeView2.showCode(" Person_E person = new Person_E(\"AAAAA\");\n" + " Person_E person2 = new Person_E(\"YYYYYY\");\n" + " TestObjectLockThread t3 = new TestObjectLockThread(person);\n" + " TestObjectLockThread t4 = new TestObjectLockThread(person2);\n" + " t3.start();\n" + " t4.start();\n" + "\n" + "\n" + "" + " /**\n" + " * synchronized 修飾非靜態,方法,默認獲取自身對象的鎖,因此在多線程的狀況下\n" + " *\n" + " * 只有單例模式才能保證同步\n" + " *\n" + " */\n" + "\n" + " public synchronized void say()\n" + " {\n" + " for (int i=0;i<10000;i++) {\n" + "\n" + " Log.i(\"info\",name +\"說話內容=\"+ i);\n" + " }\n" + "\n" + " }\n" + "\n" + "\n" + " 運行發現同步失效,使用同一個Person 就會沒問題"+ "\n" + "\n" + "\n" + "對象鎖實現二\n" + " MyLock myLock = new MyLock();\n" + " TestObjectLock2Thread t5 = new TestObjectLock2Thread(myLock,1);\n" + " TestObjectLock2Thread t6 = new TestObjectLock2Thread(myLock,2);\n" + "\n" + " t5.start();\n" + " t6.start();" + " public class TestObjectLock2Thread extends Thread{\n" + "\n" + " private MyLock myLock;\n" + " private int number;\n" + " public TestObjectLock2Thread(MyLock myLock,int number){\n" + " this.myLock = myLock;\n" + " this.number = number;\n" + "\n" + " }\n" + " @Override\n" + " public void run() {\n" + " super.run();\n" + " synchronized (myLock){\n" + " for (int i = 0;i<1000;i++){\n" + " Log.i(\"info\", \"number=\" + number + \"say=\" + i);\n" + " }\n" + " }\n" + "\n" + " }\n" + " }"); // // MyLock myLock = new MyLock(); // TestObjectLock2Thread t5 = new TestObjectLock2Thread(myLock,1); // TestObjectLock2Thread t6 = new TestObjectLock2Thread(myLock,2); // // t5.start(); // t6.start(); } @Override public void onClick(View view) { // tvResult.setText(Arrays.toString(arrays)); } public class TestObjectLock2Thread extends Thread{ private MyLock myLock; private int number; public TestObjectLock2Thread(MyLock myLock,int number){ this.myLock = myLock; this.number = number; } @Override public void run() { super.run(); synchronized (myLock){ for (int i = 0;i<1000;i++){ Log.i("info", "number=" + number + "say=" + i); } } } } public class TestObjectLockThread extends Thread{ private Person person; public TestObjectLockThread(Person person){ this.person = person; } @Override public void run() { super.run(); person.say(); } } public static class TestThread extends Thread { private int number; public TestThread(int number) { this.number = number; } @Override public void run() { super.run(); test(number); } // //類鎖實現之一 // private static synchronized void test(final int number) { // for (int i=0;i<10000;i++) { // // Log.i("info", "number=" + number +"say="+ i); // } // } private void test(int number) { synchronized (TestThread.class) { for (int i = 0; i < 10000; i++) { Log.i("info", "number=" + number + "say=" + i); } } } } public class MyLock{ } }
## 圖 ##術語詳解 - 圖 對於圖G=(V,E) 圖形結構,簡稱「圖」,是一種複雜的數據結構。圖形結構中,每一個結點的前驅結點數和後續結點數能夠任意多個。 圖是由頂點集合以及頂點間的關係集合組成的一種數據結構。 - 頂點(Vertex) - 弧(Arc) 有向邊:若從頂點Vi到Vj的邊有方向,則稱這條邊爲有向邊,也稱爲弧。 - 弧頭(初始點) 若從頂點Vi到Vj的邊有方向,則稱Vi弧頭 - 弧尾(終結點) 若從定點Vi到Vj的邊有方向,則稱Vj弧尾 - 邊(Edge) 無向圖的連線叫邊 - 無向圖(Undigraph) 邊沒有方向的圖稱爲無向圖。 G=(V, {A})、0≤邊≤n(n-1)/2 1.V是非空集合,稱爲頂點集。 2.E是V中元素構成的無序二元組的集合,稱爲邊集。 - 有向圖(Directed graph) 邊有方向的圖稱爲有向圖 G=(V, {E})、0≤弧≤n(n-1) - 無向徹底圖 (徹底無向圖) 如有n個頂點的無向圖有n(n-1)/2 條邊, 則此圖爲徹底無向圖。 - 有向徹底圖(徹底有向圖)有n個頂點的有向圖有n(n-1)條邊, 則此圖爲徹底有向圖。 - 稀疏圖(Sparse graph) |E|遠遠小於|V|^2 的圖,(有的書上說,當邊數e<<n㏒2n時,圖G稱爲稀疏) - 稠密圖(Dense graph) |E|接近|V|^2 的圖 ## 網 - 網(network) 網裏面對應的邊是有權值的,用以表示邊的某種屬性好比距離等。而圖的邊是沒有權值的 - 權(weigh) 在處理有關圖的實際問題時,每每有值的存在,好比千米數,運費,城市,口數以及電話部數等。通常這個值成爲權值 - 無向網 - 有向網 - 子圖(Subgraph) - 鄰接點(Adjacent) - 度(Degree) 圖中的度:所謂頂點的度(degree),就是指和該頂點相關聯的邊數 - 入度(Indegree) 以某頂點爲弧頭,終止於該頂點的弧的數目稱爲該頂點的入度 - 出度(Outdegree) - 連通 在一個無向圖 G 中,若從頂點i到頂點j有路徑相連(固然從j到i也必定有路徑),則稱i和j是連通的。 若是 G 是有向圖,那麼鏈接i和j的路徑中全部的邊都必須同向。 若是圖中任意兩點都是連通的,那麼圖被稱做連通圖。 若是此圖是有向圖,則稱爲強連通圖(注意:須要雙向都有路徑)。 - 簡單路徑: 是一條x到y的連通路徑,x和y分別是起點和終點。當x=y時, 被稱爲迴路。若是通路 中的邊兩兩不一樣,則 是一條簡單通路,不然爲一條複雜通路 - 弱連通圖:將有向圖的全部的有向邊替換爲無向邊,所獲得的圖稱爲原圖的基圖。若是一個有向圖的基圖是連通圖,則有向圖是弱連通圖。 - 連通份量:無向圖 G的一個極大連通子圖稱爲 G的一個連通份量(或連通分支)。連通圖只有一個連通份量,即其自身;非連通的無向圖有多個連通份量。 生成樹 ## 圖的存儲方式 1.鄰接矩陣:就是二維數組,能夠快速定位到指定的邊,可是若是是稀疏的圖,會比較浪費空間。 2.鄰接表:適合稀疏圖,節省空間,存儲方式決定了它只能表示某個頂點的入度或者出度,不能快速定位到某一條邊。 3.十字鏈表 4.鄰接多重表 5.邊集數組 極小連通子圖 有向樹 出度(Outdegree) 路徑(path) 迴路(環) 簡單路徑 簡單迴路(簡單環) 連通 連通圖(Connected graph)、 連通份量(Connected Component)、 強連通圖、 強連通份量(有向圖中的極大強連通子圖)、 生成樹、 極小連通子圖、 有向樹。
package com.wangpos.datastructure.graph; import android.util.Log; /** * Created by qiyue on 2018/1/8. * <p> * 無向圖的鄰接表存儲方式 */ public class UndirectedGraph { /** * 整個數組表示一個圖,也就是多個頭結點信息結合構成 */ private VNode mVNodeArrays[]; /** * 圖的大小 */ private int size; /** * 建立圖(用已提供的矩陣) * <p> * vexs -- 頂點數組 * edges -- 邊數組 */ public UndirectedGraph(String[] vexs, String[][] edges) { size = vexs.length; mVNodeArrays = new VNode[size]; //初始化定點信息 for (int i = 0; i < size; i++) { mVNodeArrays[i] = new VNode(); mVNodeArrays[i].data = vexs[i]; mVNodeArrays[i].firstEdge = null; } //將頂點和邊連接一塊兒 for (int j = 0; j < size; j++) { String start = edges[j][0]; String end = edges[j][1]; int startPosition = getPosition(start); int endPosition = getPosition(end); ENode eNode = new ENode(endPosition); if (mVNodeArrays[startPosition].firstEdge == null) { mVNodeArrays[startPosition].firstEdge = eNode; } else { linkLast(mVNodeArrays[startPosition].firstEdge, eNode); } } } private int getPosition(String start) { int target = -1; for (int i = 0; i < size; i++) { String data = mVNodeArrays[i].data; if (data.equals(start)) { target = i; break; } } return target; } private void linkLast(ENode list, ENode node) { ENode p = list; while (p.nextEdge != null) p = p.nextEdge; p.nextEdge = node; } /** * 頭結點信息 */ private class VNode { public String data;//直接用String也能夠,就是浪費了一點空間 public ENode firstEdge; } /** * 邊,經過該邊對象能夠知道該末尾端點和下一條邊 */ private class ENode { public int ivex; //該邊對應結束點的位置 public ENode nextEdge; // 這裏是爲了連接下一邊 public ENode(int ivex) { this.ivex = ivex; } } /** * I/tu ( 7206): 0A>2(C)>3(D)>5(F) I/tu ( 7206): 1B I/tu ( 7206): 2C>1(B)>3(D) I/tu ( 7206): 3D I/tu ( 7206): 4E I/tu ( 7206): 5F>6(G) I/tu ( 7206): 6G>4(E) */ public void print() { System.out.printf("List Graph:\n"); for (int i = 0; i < mVNodeArrays.length; i++) { // Log.i("tu", "頂點>>"+i + "" + mVNodeArrays[i].data); StringBuilder sb = new StringBuilder(); sb.append("" + i + "" + mVNodeArrays[i].data); ENode node = mVNodeArrays[i].firstEdge; while (node != null) { sb.append(">" + node.ivex + "(" + mVNodeArrays[node.ivex].data + ")"); node = node.nextEdge; } Log.i("tu", sb.toString()); // System.out.printf("\n"); } } /** * 深度優先搜索遍歷圖 A C B D F G E */ public void DFS() { boolean[] visited = new boolean[mVNodeArrays.length]; // 頂點訪問標記 // 初始化全部頂點都沒有被訪問 for (int i = 0; i < mVNodeArrays.length; i++) visited[i] = false; Log.i("tu", "DFS:"); for (int i = 0; i < mVNodeArrays.length; i++) { if (!visited[i]) DFS(i, visited); } Log.i("tu", "\n"); } /** * 深度優先搜索 * @param i * @param visited */ private void DFS(int i, boolean[] visited) { ENode node; visited[i] = true; // System.out.printf("%c ", mVNodeArrays[i].data); Log.i("tu", mVNodeArrays[i].data); node = mVNodeArrays[i].firstEdge; while (node != null) { if (!visited[node.ivex]) DFS(node.ivex, visited); node = node.nextEdge; } } /** * 廣度優先搜索 A C D F B G E */ public void BFS() { boolean[] visited = new boolean[mVNodeArrays.length]; // 頂點訪問標記 // 初始化全部頂點都沒有被訪問 for (int i = 0; i < mVNodeArrays.length; i++) { visited[i] = false; } Log.i("tu", "BFS"); int head = 0; int rear = 0; int[] queue = new int[mVNodeArrays.length]; for (int i = 0; i < mVNodeArrays.length; i++) { if (!visited[i]) { visited[i] = true; Log.i("tu", "y" + mVNodeArrays[i].data); //入列 queue[rear] = i; rear++; } //rear以前的都是被訪問的點,經過header 去訪問每一個點下一層,訪問的點經過rear位置加入隊列 while (head != rear) { int j = queue[head]; ENode node = mVNodeArrays[j].firstEdge; // Log.i("tu", "node--"+mVNodeArrays[j].data +"node="+node); // 開始遍歷j的全部邊,而且入隊列 start while (node != null) { int k = node.ivex; // Log.i("tu", "node--"+mVNodeArrays[j].data +"k="+k+"visited[k]= "+visited[k]); if (!visited[k]) { visited[k] = true; Log.i("tu", "" + mVNodeArrays[k].data); queue[rear] = k; rear++; } node = node.nextEdge; } // 開始遍歷j的全部邊,end // Log.i("tu", "》》》》" ); //出隊列, head++; } } } }
package com.wangpos.datastructure.graph; import android.util.Log; /** * Created by qiyue on 2018/1/8. * <p> * 無向圖的鄰接表存儲方式 */ public class UndirectedGraph { /** * 整個數組表示一個圖,也就是多個頭結點信息結合構成 */ private VNode mVNodeArrays[]; /** * 圖的大小 */ private int size; /** * 建立圖(用已提供的矩陣) * <p> * vexs -- 頂點數組 * edges -- 邊數組 */ public UndirectedGraph(String[] vexs, String[][] edges) { size = vexs.length; mVNodeArrays = new VNode[size]; //初始化定點信息 for (int i = 0; i < size; i++) { mVNodeArrays[i] = new VNode(); mVNodeArrays[i].data = vexs[i]; mVNodeArrays[i].firstEdge = null; } //將頂點和邊連接一塊兒 for (int j = 0; j < size; j++) { String start = edges[j][0]; String end = edges[j][1]; int startPosition = getPosition(start); int endPosition = getPosition(end); ENode eNode = new ENode(endPosition); if (mVNodeArrays[startPosition].firstEdge == null) { mVNodeArrays[startPosition].firstEdge = eNode; } else { linkLast(mVNodeArrays[startPosition].firstEdge, eNode); } } } private int getPosition(String start) { int target = -1; for (int i = 0; i < size; i++) { String data = mVNodeArrays[i].data; if (data.equals(start)) { target = i; break; } } return target; } private void linkLast(ENode list, ENode node) { ENode p = list; while (p.nextEdge != null) p = p.nextEdge; p.nextEdge = node; } /** * 頭結點信息 */ private class VNode { public String data;//直接用String也能夠,就是浪費了一點空間 public ENode firstEdge; } /** * 邊,經過該邊對象能夠知道該末尾端點和下一條邊 */ private class ENode { public int ivex; //該邊對應結束點的位置 public ENode nextEdge; // 這裏是爲了連接下一邊 public ENode(int ivex) { this.ivex = ivex; } } /** * I/tu ( 7206): 0A>2(C)>3(D)>5(F) I/tu ( 7206): 1B I/tu ( 7206): 2C>1(B)>3(D) I/tu ( 7206): 3D I/tu ( 7206): 4E I/tu ( 7206): 5F>6(G) I/tu ( 7206): 6G>4(E) */ public void print() { System.out.printf("List Graph:\n"); for (int i = 0; i < mVNodeArrays.length; i++) { // Log.i("tu", "頂點>>"+i + "" + mVNodeArrays[i].data); StringBuilder sb = new StringBuilder(); sb.append("" + i + "" + mVNodeArrays[i].data); ENode node = mVNodeArrays[i].firstEdge; while (node != null) { sb.append(">" + node.ivex + "(" + mVNodeArrays[node.ivex].data + ")"); node = node.nextEdge; } Log.i("tu", sb.toString()); // System.out.printf("\n"); } } /** * 深度優先搜索遍歷圖 A C B D F G E */ public void DFS() { boolean[] visited = new boolean[mVNodeArrays.length]; // 頂點訪問標記 // 初始化全部頂點都沒有被訪問 for (int i = 0; i < mVNodeArrays.length; i++) visited[i] = false; Log.i("tu", "DFS:"); for (int i = 0; i < mVNodeArrays.length; i++) { if (!visited[i]) DFS(i, visited); } Log.i("tu", "\n"); } /** * 深度優先搜索 * @param i * @param visited */ private void DFS(int i, boolean[] visited) { ENode node; visited[i] = true; // System.out.printf("%c ", mVNodeArrays[i].data); Log.i("tu", mVNodeArrays[i].data); node = mVNodeArrays[i].firstEdge; while (node != null) { if (!visited[node.ivex]) DFS(node.ivex, visited); node = node.nextEdge; } } /** * 廣度優先搜索 A C D F B G E */ public void BFS() { boolean[] visited = new boolean[mVNodeArrays.length]; // 頂點訪問標記 // 初始化全部頂點都沒有被訪問 for (int i = 0; i < mVNodeArrays.length; i++) { visited[i] = false; } Log.i("tu", "BFS"); int head = 0; int rear = 0; int[] queue = new int[mVNodeArrays.length]; for (int i = 0; i < mVNodeArrays.length; i++) { if (!visited[i]) { visited[i] = true; Log.i("tu", "y" + mVNodeArrays[i].data); //入列 queue[rear] = i; rear++; } //rear以前的都是被訪問的點,經過header 去訪問每一個點下一層,訪問的點經過rear位置加入隊列 while (head != rear) { int j = queue[head]; ENode node = mVNodeArrays[j].firstEdge; // Log.i("tu", "node--"+mVNodeArrays[j].data +"node="+node); // 開始遍歷j的全部邊,而且入隊列 start while (node != null) { int k = node.ivex; // Log.i("tu", "node--"+mVNodeArrays[j].data +"k="+k+"visited[k]= "+visited[k]); if (!visited[k]) { visited[k] = true; Log.i("tu", "" + mVNodeArrays[k].data); queue[rear] = k; rear++; } node = node.nextEdge; } // 開始遍歷j的全部邊,end // Log.i("tu", "》》》》" ); //出隊列, head++; } } } }
package com.wangpos.datastructure.graph; import android.util.Log; /** * Created by qiyue on 2018/1/9. * * 無向圖的鄰接矩陣存儲方式 */ public class UndirectedGraphMatrix { public String[] getmVexs() { return mVexs; } public void setmVexs(String[] mVexs) { this.mVexs = mVexs; } public int[][] getmMatrix() { return mMatrix; } public void setmMatrix(int[][] mMatrix) { this.mMatrix = mMatrix; } private String[] mVexs; // 頂點集合 private int[][] mMatrix; // 鄰接矩陣 public UndirectedGraphMatrix(String []vexs,String [][]edges){ // 初始化"頂點數"和"邊數" int vlen = vexs.length; int elen = edges.length; // 初始化"頂點" mVexs = new String[vlen]; for (int i = 0; i < mVexs.length; i++) mVexs[i] = vexs[i]; // 初始化"邊" mMatrix = new int[vlen][vlen]; for (int i = 0; i < elen; i++) { // 讀取邊的起始頂點和結束頂點 int p1 = getPosition(edges[i][0]); int p2 = getPosition(edges[i][1]); /** * 無向圖是這樣的 */ mMatrix[p1][p2] = 1; mMatrix[p2][p1] = 1; } } private int getPosition(String s) { for(int i=0; i<mVexs.length; i++) { if (mVexs[i].equals(s)) { return i; } } return -1; } /* * 返回頂點v的第一個鄰接頂點的索引,失敗則返回-1 */ private int firstVertex(int v) { if (v<0 || v>(mVexs.length-1)) return -1; for (int i = 0; i < mVexs.length; i++) if (mMatrix[v][i] == 1) return i; return -1; } /* * 返回頂點v相對於w的下一個鄰接頂點的索引,失敗則返回-1 */ private int nextVertex(int v, int w) { if (v<0 || v>(mVexs.length-1) || w<0 || w>(mVexs.length-1)) return -1; for (int i = w + 1; i < mVexs.length; i++) if (mMatrix[v][i] == 1) return i; return -1; } /* * 深度優先搜索遍歷圖的遞歸實現 */ private void DFS(int i, boolean[] visited) { visited[i] = true; Log.i("tu",mVexs[i]); // 遍歷該頂點的全部鄰接頂點。如果沒有訪問過,那麼繼續往下走 for (int w = firstVertex(i); w >= 0; w = nextVertex(i, w)) { if (!visited[w]) DFS(w, visited); } } /* * 深度優先搜索遍歷圖 */ public void DFS() { boolean[] visited = new boolean[mVexs.length]; // 頂點訪問標記 // 初始化全部頂點都沒有被訪問 for (int i = 0; i < mVexs.length; i++) visited[i] = false; Log.i("tu","DFS: "); for (int i = 0; i < mVexs.length; i++) { if (!visited[i]) DFS(i, visited); } Log.i("tu",""); } /* * 廣度優先搜索(相似於樹的層次遍歷) */ public void BFS() { int head = 0; int rear = 0; int[] queue = new int[mVexs.length]; // 輔組隊列 boolean[] visited = new boolean[mVexs.length]; // 頂點訪問標記 for (int i = 0; i < mVexs.length; i++) visited[i] = false; Log.i("tu","BFS: "); for (int i = 0; i < mVexs.length; i++) { if (!visited[i]) { visited[i] = true; Log.i("tu", mVexs[i]); queue[rear++] = i; // 入隊列 } while (head != rear) { int j = queue[head++]; // 出隊列 for (int k = firstVertex(j); k >= 0; k = nextVertex(j, k)) { //k是爲訪問的鄰接頂點 if (!visited[k]) { visited[k] = true; Log.i("tu", mVexs[k]); queue[rear++] = k; } } } } Log.i("tu",""); } }
package com.wangpos.datastructure.graph; import android.util.Log; /** * Created by qiyue on 2018/1/9. * * 無向圖的鄰接矩陣存儲方式 */ public class UndirectedGraphMatrix { public String[] getmVexs() { return mVexs; } public void setmVexs(String[] mVexs) { this.mVexs = mVexs; } public int[][] getmMatrix() { return mMatrix; } public void setmMatrix(int[][] mMatrix) { this.mMatrix = mMatrix; } private String[] mVexs; // 頂點集合 private int[][] mMatrix; // 鄰接矩陣 public UndirectedGraphMatrix(String []vexs,String [][]edges){ // 初始化"頂點數"和"邊數" int vlen = vexs.length; int elen = edges.length; // 初始化"頂點" mVexs = new String[vlen]; for (int i = 0; i < mVexs.length; i++) mVexs[i] = vexs[i]; // 初始化"邊" mMatrix = new int[vlen][vlen]; for (int i = 0; i < elen; i++) { // 讀取邊的起始頂點和結束頂點 int p1 = getPosition(edges[i][0]); int p2 = getPosition(edges[i][1]); /** * 無向圖是這樣的 */ mMatrix[p1][p2] = 1; mMatrix[p2][p1] = 1; } } private int getPosition(String s) { for(int i=0; i<mVexs.length; i++) { if (mVexs[i].equals(s)) { return i; } } return -1; } /* * 返回頂點v的第一個鄰接頂點的索引,失敗則返回-1 */ private int firstVertex(int v) { if (v<0 || v>(mVexs.length-1)) return -1; for (int i = 0; i < mVexs.length; i++) if (mMatrix[v][i] == 1) return i; return -1; } /* * 返回頂點v相對於w的下一個鄰接頂點的索引,失敗則返回-1 */ private int nextVertex(int v, int w) { if (v<0 || v>(mVexs.length-1) || w<0 || w>(mVexs.length-1)) return -1; for (int i = w + 1; i < mVexs.length; i++) if (mMatrix[v][i] == 1) return i; return -1; } /* * 深度優先搜索遍歷圖的遞歸實現 */ private void DFS(int i, boolean[] visited) { visited[i] = true; Log.i("tu",mVexs[i]); // 遍歷該頂點的全部鄰接頂點。如果沒有訪問過,那麼繼續往下走 for (int w = firstVertex(i); w >= 0; w = nextVertex(i, w)) { if (!visited[w]) DFS(w, visited); } } /* * 深度優先搜索遍歷圖 */ public void DFS() { boolean[] visited = new boolean[mVexs.length]; // 頂點訪問標記 // 初始化全部頂點都沒有被訪問 for (int i = 0; i < mVexs.length; i++) visited[i] = false; Log.i("tu","DFS: "); for (int i = 0; i < mVexs.length; i++) { if (!visited[i]) DFS(i, visited); } Log.i("tu",""); } /* * 廣度優先搜索(相似於樹的層次遍歷) */ public void BFS() { int head = 0; int rear = 0; int[] queue = new int[mVexs.length]; // 輔組隊列 boolean[] visited = new boolean[mVexs.length]; // 頂點訪問標記 for (int i = 0; i < mVexs.length; i++) visited[i] = false; Log.i("tu","BFS: "); for (int i = 0; i < mVexs.length; i++) { if (!visited[i]) { visited[i] = true; Log.i("tu", mVexs[i]); queue[rear++] = i; // 入隊列 } while (head != rear) { int j = queue[head++]; // 出隊列 for (int k = firstVertex(j); k >= 0; k = nextVertex(j, k)) { //k是爲訪問的鄰接頂點 if (!visited[k]) { visited[k] = true; Log.i("tu", mVexs[k]); queue[rear++] = k; } } } } Log.i("tu",""); } }
package com.wangpos.datastructure.graph; import com.wangpos.datastructure.R; import com.wangpos.datastructure.core.BaseActivity; import com.wangpos.datastructure.core.CodeBean; import java.util.List; /** * Created by qiyue on 2018/1/9. */ public class TopologicalOrderActivity extends BaseActivity { @Override protected void initData() { addImage("發現V6和v1是沒有前驅的,因此咱們就隨機選去一個輸出,咱們先輸出V6,刪除和V6有關的邊,獲得以下圖", R.drawable.t2); addImage("而後,咱們繼續尋找沒有前驅的頂點,發現V1沒有前驅,因此輸出V1,刪除和V1有關的邊,獲得下圖的結果", R.drawable.t3); addImage("而後,咱們又發現V4和V3都是沒有前驅的,那麼咱們就隨機選取一個頂點輸出(具體看你實現的算法和圖存儲結構),咱們輸出V4,獲得以下圖結果: ", R.drawable.t4); addImage("而後,咱們輸出沒有前驅的頂點V3,獲得以下結果:", R.drawable.t5); addItem(new CodeBean("拓撲排序結果","v6–>v1—->v4—>v3—>v5—>v2")); String[] vexs = {"V1", "V2", "V3", "V4", "V5", "V6"}; String[][] edges = new String[][]{ {"V1", "V2"}, {"V1", "V4"}, {"V1", "V3"}, {"V3", "V2"}, {"V3", "V5"}, {"V4", "V5"}, {"V6", "V4"}, {"V6", "V5"} }; //建立有向圖 DirectedGraphMatrix graphMatrix = new DirectedGraphMatrix(vexs,edges); // graphMatrix.printPointDegree(); // graphMatrix.toplogicSort(); graphMatrix.toplogicSortByDFS(); // List<Integer> result = graphMatrix.getDfsResult(); addItem(new CodeBean("深度優先搜搜拓撲排序",sortByDFSCode)); } @Override protected String getTextData() { return null; } @Override protected int getImageData() { return R.drawable.t1; } @Override protected String getResultData() { return " 1.拓撲排序介紹,對一個有向無環圖(Directed Acyclic Graph簡稱DAG)G進行拓撲排序,是將G中全部頂點排成一個線性序列,使得圖中任意一對頂點u和v,若邊(u,v)∈E(G),則u在線性序列中出如今v以前。 \n" + "\n" + " 2.舉例子,當咱們想選修無人駕駛研發課程的時候,咱們須要學習機器學習課程,同時學習這個課程咱們還要學習算法,而且須要學習一門語言,這種決定了那些課程必須先執行,若是課程不少的話,咱們能夠來作一個拓撲排序,來決定要先學那些課程\n" + "\n" + " 3.拓撲排序前提,是一個有向無環圖。想一想若是咱們的選課的時候出現了環路,相互依賴了,那就沒辦法進行了\n" + "\n" + " 4.拓撲排序步驟:\t\n" + " A.\t在有向圖中選一個沒有前驅的頂點而且輸出\n" + " B. 從圖中刪除該頂點和全部以它爲尾的弧(白話就是:刪除全部和它有關的邊)\n" + " C. 重複上述兩步,直至全部頂點輸出,或者當前圖中不存在無前驅的頂點爲止,後者表明咱們的有向圖是有環的,所以,也能夠經過拓撲排序來判斷一個圖是否有環。" + "" + "5.拓撲排序的結果不必定是惟一的,有可能存在多個入度爲0的點"; } @Override protected String getTimeData() { return null; } @Override protected String getSpaceTimeData() { return null; } @Override protected String getWendingXingData() { return null; } @Override protected String getSummaryData() { return "\n" + "拓撲排序算法\n" + "\n" + "1.Kahn 算法 \n" + " 每次從該集合中取出(沒有特殊的取出規則,隨機取出也行,使用隊列/棧也行,下同)一個頂點,將該頂點放入保存結果的List中。\n" + "緊接着循環遍歷由該頂點引出的全部邊,從圖中移除這條邊,同時獲取該邊的另一個頂點,若是該頂點的入度在減去本條邊以後爲0,那麼也將這個頂點放到入度爲0的集合中。而後繼續從集合中取出一個頂點\n" + " \n" + "注意:當集合爲空以後,檢查圖中是否還存在任何邊,若是存在的話,說明圖中至少存在一條環路。不存在的話則返回結果List,此List中的順序就是對圖進行拓撲排序的結果。\n" + "\n" + "2.深度優先搜索算法 \n" + "\n" + " DFS的實現更加簡單直觀,使用遞歸實現。利用DFS實現拓撲排序,實際上只須要添加一行代碼,即上面僞碼中的最後一行:add n to L。\n" + "須要注意的是,將頂點添加到結果List中的時機是在visit方法即將退出之時。\n" + "這個算法的實現很是簡單,可是要理解的話就相對複雜一點。\n" + "關鍵在於爲何在visit方法的最後將該頂點添加到一個集合中,就能保證這個集合就是拓撲排序的結果呢?\n" + "由於添加頂點到集合中的時機是在dfs方法即將退出之時,而dfs方法自己是個遞歸方法,只要當前頂點還存在邊指向其它任何頂點,它就會遞歸調用dfs方法,而不會退出。所以,退出dfs方法,意味着當前頂點沒有指向其它頂點的邊了,即當前頂點是一條路徑上的最後一個頂點。\n" + " \n" + "下面簡單證實一下它的正確性:\n" + "考慮任意的邊v->w,當調用dfs(v)的時候,有以下三種狀況:\n" + "1. dfs(w)尚未被調用,即w尚未被mark,此時會調用dfs(w),而後當dfs(w)返回以後,dfs(v)纔會返回\n" + "2. dfs(w)已經被調用並返回了,即w已經被mark\n" + "3. dfs(w)已經被調用可是在此時調用dfs(v)的時候還未返回\n" + "須要注意的是,以上第三種狀況在拓撲排序的場景下是不可能發生的,由於若是狀況3是合法的話,就表示存在一條由w到v的路徑。而如今咱們的前提條件是由v到w有一條邊,這就致使咱們的圖中存在環路,從而該圖就不是一個有向無環圖(DAG),而咱們已經知道,非有向無環圖是不能被拓撲排序的。\n" + " \n" + "那麼考慮前兩種狀況,不管是狀況1仍是狀況2,w都會先於v被添加到結果列表中。因此邊v->w老是由結果集中後出現的頂點指向先出現的頂點。爲了讓結果更天然一些,可使用棧來做爲存儲最終結果的數據結構,從而可以保證邊v->w老是由結果集中先出現的頂點指向後出現的頂點\n"; } public static String sortByKahnCode = "" + "public void toplogicSort() {\n" + " int header = 0;\n" + " int result[] = new int[mVexs.length];\n" + " for (int i = 0; i < mVexs.length; i++) {\n" + " result[i] = -1;\n" + " }\n" + "\n" + " for (int i = 0; ; i++) {\n" + " if (inDegrees[i] == 0) {\n" + "\n" + " boolean isVisit = false;\n" + " for (int m = 0; m < header; m++) {\n" + " if (result[m] == i) {\n" + " isVisit = true;\n" + " }\n" + " }\n" + " if (!isVisit) {\n" + " result[header] = i;\n" + " deletePositin(i);\n" + " header++;\n" + " if (header == inDegrees.length) {\n" + " break;\n" + " }\n" + "\n" + " }\n" + " if (i == 5) {\n" + " i = 0;\n" + " }\n" + " }\n" + " }\n" + "\n" + " /***\n" + " * 輸出\n" + " */\n" + "\n" + " for (int i = 0; i < header; i++) {\n" + " Log.i(\"tu\", mVexs[result[i]]);\n" + " }\n" + "\n" + " }"; public static String sortByDFSCode = "\n" + " public void toplogicSortByDFS(){\n" + "\n" + "\n" + " boolean[] visited = new boolean[mVexs.length]; // 頂點訪問標記\n" + "\n" + " // 初始化全部頂點都沒有被訪問\n" + " for (int i = 0; i < mVexs.length; i++)\n" + " visited[i] = false;\n" + "\n" + " Log.i(\"tu\",\"DFS: \");\n" + " for (int i = 0; i < mVexs.length; i++) {\n" + " if (!visited[i]) {\n" + " DFS(i, visited);\n" + " }\n" + " }\n" + "\n" + " for (int i=dfsResult.size()-1;i>=0;i--){\n" + " Log.i(\"topo\",mVexs[dfsResult.get(i).intValue()]);\n" + " }\n" + " }\n" + "\n" + "\n" + "\n" + " /*\n" + " * 深度優先搜索遍歷圖的遞歸實現\n" + " */\n" + " private void DFS(int i, boolean[] visited) {\n" + "\n" + " visited[i] = true;\n" + " Log.i(\"tu\",mVexs[i]);\n" + " // 遍歷該頂點的全部鄰接頂點。如果沒有訪問過,那麼繼續往下走\n" + " for (int w = firstVertex(i); w >= 0; w = nextVertex(i, w)) {\n" + " if (!visited[w]) {\n" + " DFS(w, visited);\n" + "\n" + " }\n" + " }\n" + " dfsResult.add(i);\n" + " }"; }
package com.wangpos.datastructure.sort; import android.app.ActionBar; import android.util.Log; import com.wangpos.datastructure.R; import com.wangpos.datastructure.core.BaseActivity; import com.wangpos.datastructure.core.CodeBean; import java.util.Arrays; /** * Created by qiyue on 2017/11/22. */ public class HeapSortActivity extends BaseActivity { int arr[] = { 1, 3, 4, 5, 2, 6, 9, 7, 8, 0 }; @Override protected void initData() { setTitleText("堆排序"); addItem(new CodeBean("堆的構建建和排序",heapSortCode)); addItem(new CodeBean("堆的遞歸算法",heapAdjustRecursionCode)); addItem(new CodeBean("堆的非遞歸算法",heapAdjustIteration)); addItem(new CodeBean("堆的非遞歸算法優化",heapAdjustIterationGood)); addImage("第一次比較,找到最後一個節點的父節,根結點編號爲0開始,第i個元素,經過公式(i-1)/2獲得他的父親節點", R.drawable.dui1); addImage("第二次比較", R.drawable.dui2); addImage("第三次比較", R.drawable.dui3); addImage("第四次比較", R.drawable.dui4); addImage("第五次比較", R.drawable.dui5); addImage("一個堆結構數據", R.drawable.dui6); // Log.i("info","排序後="+Arrays.toString(arr)); } @Override protected String getTextData() { return Arrays.toString(arr); } @Override protected int getImageData() { return 0; } @Override protected String getResultData() { return Arrays.toString(heapSort(arr)); } @Override protected String getTimeData() { return "O(nlogn)"; } @Override protected String getSpaceTimeData() { return "O(1)"; } @Override protected String getWendingXingData() { return "不穩定"; } @Override protected String getSummaryData() { return " 堆排序,這裏的堆不是java中的堆,是一種數據結構,簡單的理解就是一個徹底二叉樹\n" + " 堆的定義\n" + "n個元素的序列{k1,k2,…,kn}當且僅當知足下列關係之一時,稱之爲堆。\n" + "\n" + " 情形1:ki <= k2i 且ki <= k2i+1 (最小化堆或小頂堆)\n" + "\n" + " 情形2:ki >= k2i 且ki >= k2i+1 (最大化堆或大頂堆)\n" + "\n" + "若將和此序列對應的一維數組(即以一維數組做此序列的存儲結構)當作是一個徹底二叉樹," + "則堆的含義代表,徹底二叉樹中全部非終端結點的值均不大於(或不小於)其左、右孩子結點的值。" + "\n" + "\n" + "" + "堆的存儲\n" + "" + "<<通常用數組來表示堆,若根結點存在序號0處, i結點的父結點下標就爲(i-1)/2。i結點的左右子結點下標分別爲2*i+1和2*i+2。>>\n" + "" + ""; } /** * * 通常用數組來表示堆,若根結點存在序號0處, i結點的父結點下標就爲(i-1)/2。i結點的左右子結點下標分別爲2*i+1和2*i+2。 * * * 調整堆,也能夠叫構建堆,準確的說是構建 * * 交換都是最後一步, while循環內只是覆蓋,上移,每次找出自節點最大最大值給parent賦值,自身先不變, * 下次循環自身變爲parent,找出孩子中最大值賦值給自身 * * 循環終止條件 是給定一個parent點,大於其孩子 小於 parent 就會終止, * * @param array 數組 1, 3, 4, 5, 2, 6, 9, 7, 8, 0 * @param parent * @param length */ public void HeapAdjust(int[] array, int parent, int length) { int temp = array[parent]; // temp保存當前父節點 第一次始終是0 int child = 2 * parent + 1; // 先得到左孩子 while (child < length) { /** * 兩個孩子比較大小 */ // 若是有右孩子結點,而且右孩子結點的值大於左孩子結點,則選取右孩子結點 if (child + 1 < length && array[child] < array[child + 1]) { child++; } /** * 孩子中最大的和父親比較大小,若是父親大,跳出循環,不然把最大值和父親交換 */ // 若是父結點的值已經大於孩子結點的值,則直接結束 if (temp >= array[child]) { break; } // 把孩子結點的值賦給父結點 array[parent] = array[child]; // 選取孩子結點的左孩子結點,繼續向下篩選 /** * 再採用從後構建堆的時候,這裏就會沒用 */ parent = child; child = 2 * child + 1; Log.i("info","temp="+temp +"HeapAdjust="+Arrays.toString(array)); } /** * 將本次父節點賦值給最後一個parent ,parent多是本身 */ array[parent] = temp; } private static final String heapSortCode = "/**\n" + " * 創建堆的過程必須從第一個葉子節點的父節點開始構建,原理就是,咱們必需要創建小的堆,逐漸擴大,\n" + " *\n" + " * 創建堆算法解析\n" + " *\n" + " * 第一趟按要求,從倒數第二層開始,只有兩層,從第一個葉子節點的父節點開始,判斷是否孩子中最大的,若是不是,則和孩子中最大值交換\n" + " * 第二趟指針前移動,若是仍是在倒數第二層和第一趟算法同樣\n" + " * 通過幾回指針移動後,到了倒數第三層,此時是三層結構,也判斷是否孩子中最大的,若是不是,把最大值拿過來,但最小值不要着急給出去,\n" + " * 有可能這個值小的離譜,因此繼續順着這個最大值的分支,找他的孩子比較,若是驗證已經大於孩子就中止,否者繼續向下層比較\n" + " *\n" + " * 第一趟的算法能夠寫成這樣:\n" + " *\n" + " * int temp = array[parent];\n" + " * int child = 2 * parent + 1;\n" + " * if (child + 1 < length && array[child] < array[child + 1]) {\n" + " child++;\n" + " }\n" + "\n" + " if (temp >= array[child]) {\n" + "\n" + " }else{\n" + " array[parent] = array[child];\n" + " }\n" + "\n" + " 再倒數三層以上的算法( 多出了向下查找判斷):\n" + " int temp = array[parent];\n" + " int child = 2 * parent + 1;\n" + " if (child + 1 < length && array[child] < array[child + 1]) {\n" + " child++;\n" + " }\n" + "\n" + " if (temp >= array[child]) {\n" + "\n" + " }else{\n" + " array[parent] = array[child];\n" + " }\n" + "\n" + " //至關於遞歸\n" + " parent = child;\n" + " child = 2 * parent + 1;\n" + "\n" + " *\n" + " *\n" + " */\n" + " public int[] heapSort(int[] list) {\n" + "\n" + " // 循環創建初始堆\n" + " for (int i = (list.length-1) / 2; i >= 0; i--) {\n" + "// HeapAdjust(list, i, list.length);\n" + "// heapAdjustRecursion(list,i,list.length);\n" + "// heapAdjustIteration(list,i,list.length);\n" + " heapAdjustIterationGood(list,i,list.length);\n" + " }\n" + " //初始數據[9, 8, 6, 7, 2, 1, 4, 3, 5, 0]\n" + "\n" + " Log.i(\"info\", \"初始後堆\"+Arrays.toString(list));\n" + " /**\n" + " * 當前頂點和最後一個交換後,第一個數據有可能不符合堆結構,因此咱們要找到他的位置,\n" + " * 若是第一次比較如比孩子大,那就不須要更換,否者,將孩子中最大的換到本身位置,此時空缺位置檢測放入3合不合適,\n" + " * 也就是繼續和這個位子的孩子中最大值比較,若是大於,那就是這個位置\n" + " */\n" + " for (int i = list.length - 1; i > 0; i--) {\n" + " // 最後一個元素和第一元素進行交換\n" + " int temp = list[i];\n" + " list[i] = list[0];\n" + " list[0] = temp;\n" + " //第一次交換後的數據[0, 8, 6, 7, 2, 1, 4, 3, 5, 9]\n" + "// heapAdjustRecursion(list,0,i);\n" + "// heapAdjustIteration(list,0,i);\n" + " heapAdjustIterationGood(list,0,i);\n" + " //第一趟結果[8, 7, 6, 5, 2, 1, 4, 3, 0, 9]\n" + "\n" + "// Log.i(\"info\",\"第\"+(list.length - i)+\"趟list=\"+Arrays.toString(list));\n" + "\n" + " }\n" + " return list;\n" + "\n" + " }"; /** * 創建堆的過程必須從第一個葉子節點的父節點開始構建,原理就是,咱們必需要創建小的堆,逐漸擴大, * * 創建堆算法解析 * * 第一趟按要求,從倒數第二層開始,只有兩層,從第一個葉子節點的父節點開始,判斷是否孩子中最大的,若是不是,則和孩子中最大值交換 * 第二趟指針前移動,若是仍是在倒數第二層和第一趟算法同樣 * 通過幾回指針移動後,到了倒數第三層,此時是三層結構,也判斷是否孩子中最大的,若是不是,把最大值拿過來,但最小值不要着急給出去, * 有可能這個值小的離譜,因此繼續順着這個最大值的分支,找他的孩子比較,若是驗證已經大於孩子就中止,否者繼續向下層比較 * * 第一趟的算法能夠寫成這樣: * * int temp = array[parent]; * int child = 2 * parent + 1; * if (child + 1 < length && array[child] < array[child + 1]) { child++; } if (temp >= array[child]) { }else{ array[parent] = array[child]; } 再倒數三層以上的算法( 多出了向下查找判斷): int temp = array[parent]; int child = 2 * parent + 1; if (child + 1 < length && array[child] < array[child + 1]) { child++; } if (temp >= array[child]) { }else{ array[parent] = array[child]; } //至關於遞歸 parent = child; child = 2 * parent + 1; * * */ public int[] heapSort(int[] list) { // 循環創建初始堆 for (int i = (list.length-1) / 2; i >= 0; i--) { // HeapAdjust(list, i, list.length); // heapAdjustRecursion(list,i,list.length); // heapAdjustIteration(list,i,list.length); heapAdjustIterationGood(list,i,list.length); } //初始數據[9, 8, 6, 7, 2, 1, 4, 3, 5, 0] Log.i("info", "初始後堆"+Arrays.toString(list)); /** * 當前頂點和最後一個交換後,第一個數據有可能不符合堆結構,因此咱們要找到他的位置, * 若是第一次比較如比孩子大,那就不須要更換,否者,將孩子中最大的換到本身位置,此時空缺位置檢測放入3合不合適, * 也就是繼續和這個位子的孩子中最大值比較,若是大於,那就是這個位置 */ for (int i = list.length - 1; i > 0; i--) { // 最後一個元素和第一元素進行交換 int temp = list[i]; list[i] = list[0]; list[0] = temp; //第一次交換後的數據[0, 8, 6, 7, 2, 1, 4, 3, 5, 9] // heapAdjustRecursion(list,0,i); // heapAdjustIteration(list,0,i); heapAdjustIterationGood(list,0,i); //第一趟結果[8, 7, 6, 5, 2, 1, 4, 3, 0, 9] // Log.i("info","第"+(list.length - i)+"趟list="+Arrays.toString(list)); } return list; } private static final String heapAdjustRecursionCode = "/**\n" + " * 遞歸方法\n" + " * 1.須要額外的方法棧空間\n" + " * 2.每次都須要交換\n" + " */\n" + " public void heapAdjustRecursion(int array[],int parent,int length){\n" + "\n" + " int temp = array[parent];\n" + " int child = 2 * parent + 1;\n" + "\n" + " if (child >=length){\n" + " Log.i(\"info\",\"child=\"+child+\"heapAdjustRecursion 結束\");\n" + " return;\n" + " }\n" + " if (child + 1 < length && array[child] < array[child + 1]) {\n" + " child++;\n" + " }\n" + "\n" + " if (temp >= array[child]) {\n" + "\n" + " }else{\n" + " array[parent] = array[child];\n" + " array[child] = temp;\n" + " }\n" + " parent = child;\n" + "\n" + " heapAdjustRecursion(array,parent,length);\n" + " }"; /** * 遞歸方法 * 1.須要額外的方法棧空間 * 2.每次都須要交換 */ public void heapAdjustRecursion(int array[],int parent,int length){ int temp = array[parent]; int child = 2 * parent + 1; if (child >=length){ Log.i("info","child="+child+"heapAdjustRecursion 結束"); return; } if (child + 1 < length && array[child] < array[child + 1]) { child++; } if (temp >= array[child]) { }else{ array[parent] = array[child]; array[child] = temp; } parent = child; heapAdjustRecursion(array,parent,length); } private static final String heapAdjustIteration = "/**\n" + " * 迭代算法(非遞歸算法)\n" + " * 每次都交換\n" + " */\n" + " public void heapAdjustIteration(int array[],int parent,int length){\n" + " int temp = array[parent];\n" + " int child = 2 *parent + 1;\n" + "\n" + " while(child<length){\n" + " /**選出最大child**/\n" + " if (child + 1<length && array[child]<array[child +1]){\n" + " child ++;\n" + " }\n" + "\n" + " if(temp>array[child]){\n" + " Log.i(\"info\",\"heapAdjustIteration結束\");\n" + " break;\n" + " }else{\n" + " array[parent] = array[child];\n" + " array[child] = temp;\n" + " parent = child;\n" + " child = 2 *parent +1;\n" + " }\n" + "\n" + " }\n" + "\n" + " }"; /** * 迭代算法(非遞歸算法) * 每次都交換 */ public void heapAdjustIteration(int array[],int parent,int length){ int temp = array[parent]; int child = 2 *parent + 1; while(child<length){ /**選出最大child**/ if (child + 1<length && array[child]<array[child +1]){ child ++; } if(temp>array[child]){ Log.i("info","heapAdjustIteration結束"); break; }else{ array[parent] = array[child]; array[child] = temp; parent = child; child = 2 *parent +1; } } } private static final String heapAdjustIterationGood = " /**\n" + " * 迭代算法(優化版)(非遞歸算法)\n" + " * 賦值不交換,最後一次再交換,減小通常的交換次數,也就是肯定最終位置(和選擇排序同樣)\n" + " */\n" + " public void heapAdjustIterationGood(int array[],int parent,int length){\n" + " int temp = array[parent];\n" + " int child = 2 *parent + 1;\n" + "\n" + " while(child<length){\n" + " /**選出最大child**/\n" + " if (child + 1<length && array[child]<array[child +1]){\n" + " child ++;\n" + " }\n" + "\n" + " if(temp>array[child]){\n" + " Log.i(\"info\",\"heapAdjustIteration結束\");\n" + " break;\n" + " }else{\n" + " array[parent] = array[child];\n" + "\n" + " parent = child;\n" + " child = 2 *parent +1;\n" + " }\n" + "\n" + " }\n" + " //指向最後一個,child 可能指向沒有\n" + " array[parent] = temp;\n" + "// array[child] = temp;\n" + "\n" + " }"; /** * 迭代算法(優化版)(非遞歸算法) * 賦值不交換,最後一次再交換,減小通常的交換次數,也就是肯定最終位置(和選擇排序同樣) */ public void heapAdjustIterationGood(int array[],int parent,int length){ int temp = array[parent]; int child = 2 *parent + 1; while(child<length){ /**選出最大child**/ if (child + 1<length && array[child]<array[child +1]){ child ++; } if(temp>array[child]){ Log.i("info","heapAdjustIteration結束"); break; }else{ array[parent] = array[child]; parent = child; child = 2 *parent +1; } } //指向最後一個,child 可能指向沒有 array[parent] = temp; // array[child] = temp; } }
package com.wangpos.datastructure.sort; import android.util.Log; import com.wangpos.datastructure.core.BaseActivity; import com.wangpos.datastructure.core.CodeBean; import java.util.Arrays; /** * Created by qiyue on 2017/11/23. */ public class MergeSortActivity extends BaseActivity { int arrays[] = {4,7,5,3,2,8,6,1}; @Override protected void initData() { setTitleText("歸併排序"); addItem(new CodeBean("歸併排序",mergeCode)); } @Override protected String getTextData() { return Arrays.toString(arrays); } @Override protected int getImageData() { return 0; } @Override protected String getResultData() { MergeSort(arrays); return Arrays.toString(arrays); } @Override protected String getTimeData() { return "對長度爲n的文件,需進行 趟二路歸併,每趟歸併的時間爲O(n),故其時間複雜度不管是在最好狀況下仍是在最壞狀況下均是O(nlgn)。"; } @Override protected String getSpaceTimeData() { return "須要一個輔助向量來暫存兩有序子文件歸併的結果,故其輔助空間複雜度爲O(n),顯然它不是就地排序。"; } @Override protected String getWendingXingData() { return "穩定"; } @Override protected String getSummaryData() { return "歸併排序 \n" + " 歸併排序 (merge sort) 是一類與插入排序、交換排序、選擇排序不一樣的另外一種排序方法。歸併的含義是將兩個或兩個以上的有序表合併成一個新的有序表。歸併排序有多路歸併排序、兩路歸併排序 , 可用於內排序,也能夠用於外排序。這裏僅對內排序的兩路歸併方法進行討論。 \n" + "1.兩路歸併排序算法思路\n" + " ①把 n 個記錄當作 n 個長度爲1的有序子表;\n" + " ②進行兩兩歸併使記錄關鍵字有序,獲得 n/2 個長度爲 2 的有序子表; \n" + " ③重複第②步直到全部記錄歸併成一個長度爲 n 的有序表爲止。"; } private static void MergeSort(int[] a) { Log.i("info","開始排序"); Sort(a, 0, a.length - 1); } private static void Sort(int[] a, int left, int right) { if(left>=right) return; int mid = (left + right) / 2; //二路歸併排序裏面有兩個Sort,多路歸併排序裏面寫多個Sort就能夠了 Sort(a, left, mid); Sort(a, mid + 1, right); merge(a, left, mid, right); } /** * * 算法爲三個方法 * * 歸併排序是先拆分,按照2分或者3分等等,而後將最小不可分的 * * 而後須要一個輔助控件 * 和輔助的cIndex = left 以便後面拷貝 * 須要一個tmpIndex臨時變量 * 和rightIndex做爲右邊判斷 * * * @param a * @param left * @param mid * @param right */ private static void merge(int[] a, int left, int mid, int right) { int[] tmp = new int[a.length]; int rightIndex = mid + 1; int tmpIndex = left; int cIndex=left; /** * 左右逐個比較大小 */ while(left <=mid && rightIndex <= right) { if (a[left] <= a[rightIndex]) tmp[tmpIndex++] = a[left++]; else tmp[tmpIndex++] = a[rightIndex++]; } /** 比較過程有可能左邊剩餘,將左邊剩餘的歸併 */ while (left <=mid) { tmp[tmpIndex++] = a[left++]; } /** 比較過程有可能右邊剩餘,將右邊剩餘的歸併 */ while ( rightIndex <= right ) { tmp[tmpIndex++] = a[rightIndex++]; } // System.out.println("第"+(++number)+"趟排序:\t"); /** 從臨時數組拷貝到原數組 **/ while(cIndex<=right){ a[cIndex]=tmp[cIndex]; //輸出中間歸併排序結果 System.out.print(a[cIndex]+"\t"); cIndex++; } System.out.println(); } private static final String mergeCode = " private static void MergeSort(int[] a) {\n" + " Log.i(\"info\",\"開始排序\");\n" + " Sort(a, 0, a.length - 1);\n" + " }\n" + "\n" + " private static void Sort(int[] a, int left, int right) {\n" + " if(left>=right)\n" + " return;\n" + "\n" + " int mid = (left + right) / 2;\n" + " //二路歸併排序裏面有兩個Sort,多路歸併排序裏面寫多個Sort就能夠了\n" + " Sort(a, left, mid);\n" + " Sort(a, mid + 1, right);\n" + " merge(a, left, mid, right);\n" + "\n" + " }\n" + "\n" + "\n" + " private static void merge(int[] a, int left, int mid, int right) {\n" + "\n" + " int[] tmp = new int[a.length];\n" + " int rightIndex = mid + 1;\n" + " int tmpIndex = left;\n" + " int cIndex=left;\n" + " /**\n" + " * 左右逐個比較大小\n" + " */\n" + " while(left <=mid && rightIndex <= right) {\n" + " if (a[left] <= a[rightIndex])\n" + " tmp[tmpIndex++] = a[left++];\n" + " else\n" + " tmp[tmpIndex++] = a[rightIndex++];\n" + " }\n" + " /** 比較過程有可能左邊剩餘,將左邊剩餘的歸併 */\n" + " while (left <=mid) {\n" + " tmp[tmpIndex++] = a[left++];\n" + " }\n" + " /** 比較過程有可能右邊剩餘,將右邊剩餘的歸併 */\n" + " while ( rightIndex <= right ) {\n" + " tmp[tmpIndex++] = a[rightIndex++];\n" + " }\n" + "// System.out.println(\"第\"+(++number)+\"趟排序:\\t\");\n" + " /** 從臨時數組拷貝到原數組 **/\n" + " while(cIndex<=right){\n" + " a[cIndex]=tmp[cIndex];\n" + " //輸出中間歸併排序結果\n" + " System.out.print(a[cIndex]+\"\\t\");\n" + " cIndex++;\n" + " }\n" + " System.out.println();\n" + " }"; }
package com.wangpos.datastructure.sort; import android.widget.TextView; import com.wangpos.datastructure.R; import com.wangpos.datastructure.core.BaseActivity; import com.wangpos.datastructure.core.CodeBean; import java.util.Arrays; /** * Created by qiyue on 2017/11/23. */ public class ShellSortActivity extends BaseActivity { int array[] = {82 ,31 ,29 ,71, 72, 42, 64, 5,110}; @Override protected void initData() { setTitleText("希爾排序"); addItem(new CodeBean("希爾排序",shellSortCode)); } @Override protected String getTextData() { return Arrays.toString(array); } @Override protected int getImageData() { return 0; } @Override protected String getResultData() { shellsort(array); return Arrays.toString(array); } @Override protected String getTimeData() { return "O(n^2)"; } @Override protected String getSpaceTimeData() { return null; } @Override protected String getWendingXingData() { return "不穩定"; } @Override protected String getSummaryData() { return "希爾排序就是對直接插入排序的一個優化。好比有這麼一種狀況:對一個無序數組進行從小到大的排序,可是數組的最後一個位置的數是最小的,咱們要把它挪到第一個位置,其餘位置的都要日後移動,要是這個數組很是大,那麼直接插入排序的開銷就很是大。\n" + "\n" + " 如今有一個array,希爾排序就是設定一個增量incrementNum(0<incrementNum<array.length)。\n" + "\n" + " 先從array[0]開始,以incrementNum爲增量的進行直接插入排序,直到數組末尾,而後從array[1]開始重複:以incrementNum爲增量的進行直接插入排序; 而後從array[1]開始重複......一直到array[n]。\n" + "\n" + " 而後取一個小於上一步增量的新的增量(好比設置爲incrementNum/2),對前一個步驟的結果array進行遍歷,直接插入排序....\n" + "\n" + " 再取小於上一步增量的新的增量,重複進行:遍歷,直接插入排序\n" + "\n" + " 直到新的增量小於1以後再退出循環\n" + "\n" + " 步驟1:好比如今有數組{82 ,31 ,29 ,71, 72, 42, 64, 5,110} 第一次取增量設置爲array.length/2 = 4 先從82開始以4爲增量遍歷直到末尾,獲得(82,42) 排序獲得{42 ,31 ,29 ,71, 72, 82, 64, 5,110}。 而後從第二個數31開始重複上一個步驟,獲得(31,64) 排序獲得{42 ,31 ,29 ,71, 72, 82, 64, 5,110}....... 以4爲增量的遍歷完數組以後,獲得的結果是{42 ,31,5,71,72,82,64,29,110}\n" + "\n" + " 而後從新區增量,這兒設定爲incrementNum/2 = 2,對{42 ,31,5,71,72,82,64,29,110}重複步驟1。 完事以後,在取新的增量,重複步驟1。 直到取到的增量小於1,退出循環。"; } private static final String shellSortCode = "/**\n" + " *\n" + " * @param arrays 須要排序的序列\n" + " */\n" + " public static void shellsort(int[] arrays) {\n" + " if (arrays == null || arrays.length <= 1) {\n" + " return;\n" + " }\n" + " //增量\n" + " int incrementNum = arrays.length / 2;\n" + " while (incrementNum >= 1) {\n" + " for (int i = 0; i < arrays.length; i++) {\n" + " //進行插入排序\n" + " for (int j = i; j < arrays.length - incrementNum; j = j + incrementNum) {\n" + " if (arrays[j] > arrays[j + incrementNum]) {\n" + " int temple = arrays[j];\n" + " arrays[j] = arrays[j + incrementNum];\n" + " arrays[j + incrementNum] = temple;\n" + " }\n" + " }\n" + " }\n" + " //設置新的增量\n" + " incrementNum = incrementNum / 2;\n" + " }\n" + " }"; /** * 希爾排序 * * @param arrays 須要排序的序列 */ public static void shellsort(int[] arrays) { if (arrays == null || arrays.length <= 1) { return; } //增量 int incrementNum = arrays.length / 2; while (incrementNum >= 1) { for (int i = 0; i < arrays.length; i++) { //進行插入排序 for (int j = i; j < arrays.length - incrementNum; j = j + incrementNum) { if (arrays[j] > arrays[j + incrementNum]) { int temple = arrays[j]; arrays[j] = arrays[j + incrementNum]; arrays[j + incrementNum] = temple; } } } //設置新的增量 incrementNum = incrementNum / 2; } } }
回覆關鍵字:android
一、回覆 「10」 查看 最有價值的10個spring boot開源項目git
二、回覆 「國旗」 獲取國旗頭像教程**程序員
三、回覆 「Ubuntu」 獲取**100 個最佳 Ubuntu 應用 和 linux神器github
四、回覆 「idea」 獲取**最新idea破解教程 和 裝逼神奇面試
五、回覆 「ssh」 獲取史上最好的 ssh工具 支持mac算法
六、回覆 「代金券」 免費獲取騰訊雲和阿里雲代金券
推薦閱讀:
Java 開發人員經常使用的服務配置(Nginx、Tomcat、JVM、Mysql、Redis)
面試官問我:一個 TCP 鏈接能夠發多少個 HTTP 請求?我居然回答不上來..
個人官網
個人CSDN地址http://blog.csdn.net/chenjian...
個人簡書地址http://www.jianshu.com/u/9b5d...
個人githubhttps://github.com/javanan
個人碼雲地址https://gitee.com/jamen/
阿里雲優惠券與阿里雲上雲教程<http://aliyun.guan2ye.com/>
我的微信公衆號: dou_zhe_wan
歡迎關注
免責聲明:
1.本公衆號所轉載文章均來自公開網絡。
2.若是出處標註有誤或侵犯到原著做者權益,請聯繫刪除。
3.轉載本公衆號中的文章請註明原文連接和做者,不然產生的任何版權糾紛均與本公衆號無關。