瘋狂的Java算法——從古至今的難題排序惦蚊,來一場“算林大會”

從古至今的難題

  在IT屆有一道百算不厭其煩的題幽歼,俗稱排序。不管是你參加BAT等高端筆試捞高,亦或是藏匿于街頭小巷的草根筆試氯材,都會經(jīng)常見到這樣一道百年難得一解的問題。

  今天有幸與各位分享一下算法屆的草根明星硝岗,排序?qū)玫念I(lǐng)銜大神——插入排序以及歸并排序氢哮。最后,在頭腦風暴下型檀,又有幸認識了一位新朋友冗尤,名叫并行歸并排序。接下來胀溺,咱們就一一認識一下裂七,并且在最后來一次“算林大會”吧。

插入排序簡介

  插入排序仓坞,算林稱最親民的排序算法背零,插入排序采用最簡單的插入方式對一個整數(shù)數(shù)組進行排序。它循環(huán)數(shù)組中從第二個開始的所有元素无埃,并且將每一個循環(huán)到的元素插入到相應(yīng)的位置徙瓶,從而實現(xiàn)排序的目的蝎困。

插入排序的代碼展示

  使用Java代碼描述插入排序,可以用以下的代碼倍啥。

package algorithm;

/**

* @author zuoxiaolong

*

*/

public abstract class InsertSort {

public static void sort(int[] numbers){

for (int i = 1; i < numbers.length; i++) {

int currentNumber = numbers[i];

int j = i - 1;

while (j >= 0 && numbers[j] > currentNumber) {

numbers[j + 1] = numbers[j];

j--;

}

numbers[j + 1] = currentNumber;

}

}

}

  這個算法從數(shù)組的第二個元素開始循環(huán)禾乘,將選中的元素與之前的元素一一比較,如果選中的元素小于之前的元素虽缕,則將之前的元素后移始藕,最后再將選中的元素放在合適的位置。在這個算法執(zhí)行的過程中氮趋,總是保持著索引i之前的數(shù)組是升序排列的伍派。

  插入排序理解起來比較簡單,因此就不過多的解釋它的實現(xiàn)原理了剩胁,尚未理解的猿友可以自行研究诉植。

插入排序的性能分析

  接下來,咱們來簡單分析一下插入排序的性能昵观。首先晾腔,插入排序當中有兩個循環(huán),假設(shè)數(shù)組的大小為n啊犬,則第一個循環(huán)是n-1次灼擂,第二個while循環(huán)在最壞的情況下是1到n-1次。因此插入排序的時間復(fù)雜度大約為如下形式觉至。

  1+2+3+4+...+n-1 = n(n-1)/ 2 = O(n2)

  時間復(fù)雜度為輸入規(guī)模的2次函數(shù)剔应,可見插入排序的時間復(fù)雜度是比較高的。這是原理上的簡單分析语御,最后在“算林大會”中峻贮,各位可以清楚的看到插入排序隨著輸入規(guī)模的增長,時間會指數(shù)倍的上升应闯。

歸并排序簡介

  歸并排序纤控,算林屆的新秀,引領(lǐng)著分治法的潮流孽锥。歸并排序?qū)⑴判騿栴}拆分嚼黔,比如分成兩個較小的數(shù)組细层,然后對拆分后的數(shù)組分別進行排序惜辑,最后再將排序后的較小數(shù)組進行合并。

  這種思想是一種算法設(shè)計的思想疫赎,很多問題都可以采用這種方式解決盛撑。映射到編程領(lǐng)域,其實就是遞歸的思想捧搞。因此在歸并排序的算法中抵卫,將會出現(xiàn)遞歸調(diào)用狮荔。

歸并排序的代碼展示

  歸并排序主要由兩個方法組成,一個是用于合并兩個已經(jīng)排序的數(shù)組的方法介粘,一個則是遞歸方法殖氏,用于將問題無限拆分。接下來咱們一起看看歸并排序的Java代碼展示姻采,如下所示雅采。

package algorithm;

/**

* @author zuoxiaolong

*

*/

public abstract class MergeSort {

public static void sort(int[] numbers){

sort(numbers, 0, numbers.length);

}

public static void sort(int[] numbers,int pos,int end){

if ((end - pos) > 1) {

int offset = (end + pos) / 2;

sort(numbers, pos, offset);

sort(numbers, offset, end);

merge(numbers, pos, offset, end);

}

}

public static void merge(int[] numbers,int pos,int offset,int end){

int[] array1 = new int[offset - pos];

int[] array2 = new int[end - offset];

System.arraycopy(numbers, pos, array1, 0, array1.length);

System.arraycopy(numbers, offset, array2, 0, array2.length);

for (int i = pos,j=0,k=0; i < end ; i++) {

if (j == array1.length) {

System.arraycopy(array2, k, numbers, i, array2.length - k);

break;

}

if (k == array2.length) {

System.arraycopy(array1, j, numbers, i, array1.length - j);

break;

}

if (array1[j] <= array2[k]) {

numbers[i] = array1[j++];

} else {

numbers[i] = array2[k++];

}

}

}

}

  可以看到,歸并排序?qū)⒁粋€長度為n的數(shù)組平均分為兩個n/2的數(shù)組分別進行處理慨亲,因此婚瓜,在sort方法中又調(diào)用了兩次sort方法自身。當數(shù)組大小為1時刑棵,則認為該數(shù)組為已經(jīng)為排好序的數(shù)組巴刻。因此在sort方法中,需要end與pos相差大于2時蛉签,才需要進一步拆分胡陪,這也是遞歸的終止條件。

  此外碍舍,在代碼中督弓,使用了Java提供的arraycory函數(shù)進行數(shù)組復(fù)制,這種直接復(fù)制內(nèi)存區(qū)域的方式乒验,將會比循環(huán)賦值的方式速度更快愚隧。有些算法實現(xiàn)會給merge方法中的兩個臨時數(shù)組設(shè)置哨兵,目的是為了防止merge中for循環(huán)的前兩個if判斷锻全。為了方便理解狂塘,這里沒有設(shè)置哨兵,當某一個數(shù)組的元素消耗完時鳄厌,將直接使用arraycopy方法把另外一個數(shù)組copy到numbers當中荞胡。

歸并排序的性能分析

  與插入排序一樣,咱們來簡單分析一下歸并排序的時間復(fù)雜度了嚎。咱們假設(shè)數(shù)組的大小為n泪漂,sort方法的時間復(fù)雜度為f(end-pos)。簡單的分析merge方法的復(fù)雜度歪泳,不難發(fā)現(xiàn)為(end-pos)*2萝勤,這個結(jié)果的前提是咱們認為arraycopy方法的復(fù)雜度為length參數(shù)。

  基于以上的假設(shè)呐伞,由于end-pos的初始值為n敌卓,因此歸并排序的復(fù)雜度大約為如下形式。

  2*f(n/2) + 2*n = 2*(2*f(n/4)+2*(n/2)) + 2*n=4*f(n/4) + 2*n + 2*n = n *f(1) + 2*n +...+2*n

  其中f(1)的時間復(fù)雜度為常量伶氢,假設(shè)f(1)=c趟径,而2*n將有l(wèi)og2n個瘪吏。因此咱們得到歸并排序的最終時間復(fù)雜度為如下形式。

  cn + 2n*log2n = O(n*log2n)

  歸并排序的時間復(fù)雜度與插入排序相比蜗巧,已經(jīng)降低了很多掌眠,這一點在數(shù)組的輸入規(guī)模較大時將會非常明顯,因為log函數(shù)的增加速度將遠遠低于n的增加速度幕屹。

并行歸并排序簡介

  并行歸并排序是在學(xué)習(xí)歸并排序時意淫出來的扇救,最近正在研究Java的并發(fā)編程,恰好歸并排序的子問題有一定的并行度與獨立性香嗓,因此版的并發(fā)歸并排序就這樣誕生了迅腔。事后,并行歸并排序這個家伙靠娱,發(fā)現(xiàn)早已眾所周知沧烈,不過在不知道的情況下自己能夠想到是不是也應(yīng)該竊喜一下呢。

  并行歸并排序與普通的歸并排序沒有多大區(qū)別像云,只是利用現(xiàn)在計算機多核的優(yōu)勢锌雀,在有可能的情況下,讓兩個或多個子問題的處理一起進行迅诬。這樣一來腋逆,在效率上,并行歸并排序?qū)葰w并排序更勝一籌侈贷。

并行歸并排序的代碼展示

  并行歸并排序主要對sort方法進行了修改惩歉,基礎(chǔ)的merge方法與普通的歸并排序是一樣的。因此在進行并行歸并排序時俏蛮,引用了歸并排序的一些方法撑蚌,具體的代碼如下所示。

package algorithm;

import java.util.concurrent.CountDownLatch;

/**

* @author zuoxiaolong

*

*/

public abstract class MergeParallelSort {

private static final int maxAsynDepth = (int)(Math.log(Runtime.getRuntime().availableProcessors())/Math.log(2));

public static void sort(int[] numbers) {

sort(numbers, maxAsynDepth);

}

public static void sort(int[] numbers,Integer asynDepth) {

sortParallel(numbers, 0, numbers.length, asynDepth > maxAsynDepth ? maxAsynDepth : asynDepth, 1);

}

public static void sortParallel(final int[] numbers,final int pos,final int end,final int asynDepth,final int depth){

if ((end - pos) > 1) {

final CountDownLatch mergeSignal = new CountDownLatch(2);

final int offset = (end + pos) / 2;

Thread thread1 = new SortThread(depth, asynDepth, numbers, mergeSignal, pos, offset);

Thread thread2 = new SortThread(depth, asynDepth, numbers, mergeSignal, offset, end);

thread1.start();

thread2.start();

try {

mergeSignal.await();

} catch (InterruptedException e) {}

MergeSort.merge(numbers, pos, offset, end);

}

}

static class SortThread extends Thread {

private int depth;

private int asynDepth;

private int[] numbers;

private CountDownLatch mergeSignal;

private int pos;

private int end;

/**

* @param depth

* @param asynDepth

* @param numbers

* @param mergeSignal

* @param pos

* @param end

*/

public SortThread(int depth, int asynDepth, int[] numbers, CountDownLatch mergeSignal, int pos, int end) {

super();

this.depth = depth;

this.asynDepth = asynDepth;

this.numbers = numbers;

this.mergeSignal = mergeSignal;

this.pos = pos;

this.end = end;

}

@Override

public void run() {

if (depth < asynDepth) {

sortParallel(numbers,pos,end,asynDepth,(depth + 1));

} else {

MergeSort.sort(numbers, pos, end);

}

mergeSignal.countDown();

}

}

}

  在這段代碼中搏屑,有幾點是比較特殊的争涌,簡單的說明一下。

  1辣恋,分解后的問題采用了并行的方式處理亮垫,并且咱們設(shè)定了一個參數(shù)asynDepth去控制并行的深度,通常情況下伟骨,深度為(log2CPU核數(shù))即可饮潦。

  2,當子問題不進行并行處理時底靠,并行歸并排序調(diào)用了普通歸并排序的方法害晦,比如MergeSort.sort和MergeSort.merge特铝。

  3暑中,因為合并操作依賴于兩個子問題的完成壹瘟,因此咱們設(shè)定了一個合并信號(mergeSignal),當信號發(fā)出時鳄逾,才進行合并操作稻轨。

  并行歸并排序在原理上與普通的歸并排序是一樣的,只是對于子問題的處理采用了一定程度上的并行雕凹,因此如果猿友們理解歸并排序殴俱,那么并行歸并排序并不難理解。

并行歸并排序的性能分析

  并行歸并排序只是將普通歸并排序中一些可并行的操作進行了并行處理枚抵,因此在總體的時間復(fù)雜度上并沒有質(zhì)的變化线欲,都是O(n*log2n)。

  由于并行歸并排序?qū)⒛承┡判虿僮鞑⑿胁僮髌。虼嗽谛阅苌弦欢ㄊ强煊谄胀w并排序算法的李丰。不過這也不是一定的,當數(shù)組規(guī)模太小時逼泣,并行帶來的性能提高可能會小于線程創(chuàng)建和銷毀的開銷趴泌,此時并行歸并排序的性能可能會低于普通歸并排序。

算林大會

  接下來拉庶,就是一周一度的算林大會了嗜憔,本次算林大會主要由以上三種算法參加,勝者將會成為本周度最受歡迎算法氏仗。接下來是算林大會的代碼吉捶,請各位猿友過目。

package algorithm;

import java.io.File;

import java.lang.reflect.Method;

import java.util.Random;

/**

* @author zuoxiaolong

*

*/

public class SortTests {

public static void main(String[] args) {

testAllSortIsCorrect();

testComputeTime("MergeParallelSort", 40000, 5);

testComputeTime("MergeSort", 40000, 5);

testComputeTime("InsertSort", 400, 5);

}

public static void testAllSortIsCorrect() {

File classpath = new File(SortTests.class.getResource("").getFile());

File[] classesFiles = classpath.listFiles();

for (int i = 0; i < classesFiles.length; i++) {

if (classesFiles[i].getName().endsWith("Sort.class")) {

System.out.println("---測試" + classesFiles[i].getName() + "是否有效---");

testSortIsCorrect(classesFiles[i].getName().split("\\.")[0]);

}

}

}

public static void testSortIsCorrect(String className){

for (int i = 1; i < 50; i++) {

int[] numbers = getRandomIntegerArray(1000 * i);

invoke(numbers, className);

for (int j = 1; j < numbers.length; j++) {

if (numbers[j] < numbers[j-1]) {

throw new RuntimeException(className + " sort is error because " + numbers[j] + "<" + numbers[j-1]);

}

}

}

System.out.println("---" + className + "經(jīng)測試有效---");

}

public static void testComputeTime(String className,int initNumber,int times,Object... arguments) {

long[] timeArray = new long[times];

for (int i = initNumber,j = 0; j < times; i = i * 10,j++) {

timeArray[j] = computeTime(i, className, arguments);

}

System.out.print(className + "時間增加比例:");

for (int i = 1; i < timeArray.length ; i++) {

System.out.print((float)timeArray[i]/timeArray[i - 1]);

if (i < timeArray.length - 1) {

System.out.print(",");

}

}

System.out.println();

}

public static long computeTime(int length,String className,Object... arguments){

int[] numbers = getRandomIntegerArray(length);

long start = System.currentTimeMillis();

System.out.print("開始計算長度為"+numbers.length+"方法為"+className+"參數(shù)為[");

for (int i = 0; i < arguments.length; i++) {

System.out.print(arguments[i]);

if (i < arguments.length - 1) {

System.out.print(",");

}

}

System.out.print("]皆尔,時間為");

invoke(numbers, className, arguments);

long time = System.currentTimeMillis()-start;

System.out.println(time + "ms");

return time;

}

public static int[] getRandomIntegerArray(int length){

int[] numbers = new int[length];

for (int i = 0; i < numbers.length; i++) {

numbers[i] = new Random().nextInt(length);

}

return numbers;

}

public static void invoke(int[] numbers,String className,Object... arguments){

try {

Class clazz = Class.forName("algorithm." + className);

Class[] parameterTypes = new Class[arguments.length + 1];

parameterTypes[0] = int[].class;

for (int i = 0; i < arguments.length; i++) {

parameterTypes[i + 1] = arguments[i].getClass();

}

Method method = clazz.getDeclaredMethod("sort", parameterTypes);

Object[] parameters = new Object[parameterTypes.length];

parameters[0] = numbers;

for (int i = 0; i < arguments.length; i++) {

parameters[i + 1] = arguments[i];

}

method.invoke(null, parameters);

} catch (Exception e) {

throw new RuntimeException(e);

}

}

}

  以上代碼testAllSortIsCorrect方法首先驗證了三種算法的正確性帚稠,也就是說經(jīng)過sort方法后,數(shù)組是否已經(jīng)升序排列床佳。需要一提的是滋早,由于插入排序的性能太低,因此插入排序測試的最大規(guī)模為400萬砌们,而歸并排序測試的最大規(guī)模為4億杆麸。

  接下來,大家就一起看看運行結(jié)果吧浪感。以下是在LZ的mac pro上的運行結(jié)果昔头,硬件配置為16G內(nèi)存,4核i7影兽。這種配置下揭斧,異步深度(asynDepth)默認為log24=2。

---測試InsertSort.class是否有效---

---InsertSort經(jīng)測試有效---

---測試MergeParallelSort.class是否有效---

---MergeParallelSort經(jīng)測試有效---

---測試MergeSort.class是否有效---

---MergeSort經(jīng)測試有效---

開始計算長度為40000方法為MergeParallelSort參數(shù)為[],時間為6ms

開始計算長度為400000方法為MergeParallelSort參數(shù)為[]讹开,時間為44ms

開始計算長度為4000000方法為MergeParallelSort參數(shù)為[]盅视,時間為390ms

開始計算長度為40000000方法為MergeParallelSort參數(shù)為[],時間為3872ms

開始計算長度為400000000方法為MergeParallelSort參數(shù)為[]旦万,時間為47168ms

MergeParallelSort時間增加比例:7.3333335,8.863636,9.9282055,12.181818

開始計算長度為40000方法為MergeSort參數(shù)為[]闹击,時間為7ms

開始計算長度為400000方法為MergeSort參數(shù)為[],時間為81ms

開始計算長度為4000000方法為MergeSort參數(shù)為[]成艘,時間為839ms

開始計算長度為40000000方法為MergeSort參數(shù)為[]赏半,時間為9517ms

開始計算長度為400000000方法為MergeSort參數(shù)為[],時間為104760ms

MergeSort時間增加比例:11.571428,10.358025,11.343266,11.00767

開始計算長度為400方法為InsertSort參數(shù)為[]淆两,時間為0ms

開始計算長度為4000方法為InsertSort參數(shù)為[]断箫,時間為3ms

開始計算長度為40000方法為InsertSort參數(shù)為[],時間為245ms

開始計算長度為400000方法為InsertSort參數(shù)為[]秋冰,時間為23509ms

開始計算長度為4000000方法為InsertSort參數(shù)為[]瑰枫,時間為3309180ms

InsertSort時間增加比例:Infinity,81.666664,95.9551,140.76227

  首先可以看到,三種算法都是運行正確的丹莲。接下來光坝,咱們可以對比一下三種算法的性能。

  根據(jù)輸出結(jié)果甥材,規(guī)模為400萬時的區(qū)別是最明顯與直觀的盯另。并行歸并排序僅需要390ms就完成了400萬規(guī)模的排序,而普通的歸并排序則需要839ms才可以洲赵,至于插入排序鸳惯,簡直是不可理喻,竟然需要300多萬ms叠萍,大約50分鐘芝发。

  咱們再來看三者的時間增長趨勢。兩種歸并排序基本上與規(guī)模的增長趨勢相似苛谷,每當規(guī)模增加10倍時辅鲸,時間也基本上增加10倍,而插入排序則幾乎是以100倍的速度在增加腹殿,剛好是數(shù)組規(guī)模增長速度的平方独悴。其中的Infinity是因為當數(shù)組規(guī)模為400時,毫秒級別的計時為0ms锣尉,因此當除數(shù)為0時刻炒,結(jié)果就為Infinity。

  當然了自沧,這一次結(jié)果具有一定的隨機性坟奥,猿友們可以在自己的電腦上多實驗幾次觀察一下,不過插入排序的時間實在讓人等的蛋疼。

強烈推薦《數(shù)據(jù)結(jié)構(gòu)與算法經(jīng)典問題解析》(PDF文檔)

由于細節(jié)內(nèi)容實在太多啦爱谁,所以只把部分知識點截圖出來粗略的介紹晒喷,每個小節(jié)點里面都有更細化的內(nèi)容!

整理了一份Java數(shù)據(jù)結(jié)構(gòu)與算法經(jīng)典問題解析核心知識點管行。覆蓋遞歸和回溯厨埋、鏈表邪媳、棧捐顷、隊列、樹雨效、優(yōu)先隊列和堆迅涮、隊列、優(yōu)先隊列和堆徽龟、并查集ADT叮姑、排序、選擇算法(中位數(shù))据悔、散列传透、算法設(shè)計技術(shù)、分治算法极颓、動態(tài)規(guī)劃算法朱盐、雜談等大量知識點。

如果需要獲取到這個【核心知識點整理】https://shimo.im/docs/k6xtWVdqw3tyh36p/?《Java學(xué)習(xí)菠隆、面試兵琳;文檔、視頻資源免費獲取》點擊即可獲取

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末骇径,一起剝皮案震驚了整個濱河市躯肌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌破衔,老刑警劉巖清女,帶你破解...
    沈念sama閱讀 212,686評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異晰筛,居然都是意外死亡校仑,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,668評論 3 385
  • 文/潘曉璐 我一進店門传惠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來迄沫,“玉大人,你說我怎么就攤上這事卦方⊙虼瘢” “怎么了?”我有些...
    開封第一講書人閱讀 158,160評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長尘吗。 經(jīng)常有香客問我逝她,道長,這世上最難降的妖魔是什么睬捶? 我笑而不...
    開封第一講書人閱讀 56,736評論 1 284
  • 正文 為了忘掉前任黔宛,我火速辦了婚禮,結(jié)果婚禮上擒贸,老公的妹妹穿的比我還像新娘臀晃。我一直安慰自己,他們只是感情好介劫,可當我...
    茶點故事閱讀 65,847評論 6 386
  • 文/花漫 我一把揭開白布徽惋。 她就那樣靜靜地躺著,像睡著了一般座韵。 火紅的嫁衣襯著肌膚如雪险绘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,043評論 1 291
  • 那天誉碴,我揣著相機與錄音宦棺,去河邊找鬼。 笑死黔帕,一個胖子當著我的面吹牛代咸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蹬屹,決...
    沈念sama閱讀 39,129評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼侣背,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了慨默?” 一聲冷哼從身側(cè)響起贩耐,我...
    開封第一講書人閱讀 37,872評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎厦取,沒想到半個月后潮太,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,318評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡虾攻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,645評論 2 327
  • 正文 我和宋清朗相戀三年铡买,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片霎箍。...
    茶點故事閱讀 38,777評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡奇钞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出漂坏,到底是詐尸還是另有隱情景埃,我是刑警寧澤媒至,帶...
    沈念sama閱讀 34,470評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站谷徙,受9級特大地震影響拒啰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜完慧,卻給世界環(huán)境...
    茶點故事閱讀 40,126評論 3 317
  • 文/蒙蒙 一谋旦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧屈尼,春花似錦册着、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,861評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽乞巧。三九已至涨椒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間绽媒,已是汗流浹背蚕冬。 一陣腳步聲響...
    開封第一講書人閱讀 32,095評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留是辕,地道東北人囤热。 一個月前我還...
    沈念sama閱讀 46,589評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像获三,于是被迫代替她去往敵國和親旁蔼。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,687評論 2 351

推薦閱讀更多精彩內(nèi)容

  • 概述 排序有內(nèi)部排序和外部排序疙教,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進行排序棺聊,而外部排序是因排序的數(shù)據(jù)很大,一次不能容納全部...
    蟻前閱讀 5,170評論 0 52
  • 本文主要介紹Java的七種常見排序算法的實現(xiàn)贞谓,對選擇排序限佩、插入排序、冒泡排序裸弦、歸并排序祟同、快速排序、希爾排序理疙、最小堆...
    墨雨軒夏閱讀 723評論 1 27
  • 一晕城、逼娃喝奶記 去年下半年給兒子買了一批奶粉,因為之前都是9罐一批買的窖贤,哪知道買回來后砖顷,娃突然不愛喝了暇矫!關(guān)鍵是,牌...
    成長的美好時光閱讀 296評論 2 1
  • 數(shù)據(jù)結(jié)構(gòu)算是比較重要的一門課程择吊,在找工作中也是經(jīng)常被考到李根。最近筆試老是遇到該類題目,于是就把相關(guān)知識點總結(jié)下來几睛。 ...
    龍躍十二閱讀 10,063評論 0 2
  • 愁人房轿,電話也被拉黑了。我都不知道為什么會這樣所森。如果有人對我這樣可能我會高興的跳起來吧囱持。也只好明天打電話給她舍友了,...
    f9a9585d18d5閱讀 268評論 0 0