幾種常用的排序算法代碼示例

import java.util.Arrays;

public class SortTest {

????public static void main(String... args) {

????????int[] arr = {12, 55, 22, 166, 2, 75, 30, 100, 200};

? ? ? ? bubbleSortArray(arr); //冒泡排序

? ? ? ? selectSortArray(arr); //選擇排序

? ? ? ? insertSortArray(arr); //插入排序

? ? ? ? shellSortArray(arr); //希爾排序

? ? ? ? quickSortArray(arr, 0, arr.length -1); //快速排序

? ? ? ? System.out.println("快速排序結(jié)果:" + Arrays.toString(arr));

? ? ? ? int[] arr2 =mergeSortArray(arr);

? ? ? ? System.out.println("歸并排序結(jié)果:" + Arrays.toString(arr2));

????}

????/**

? ? * 冒泡(Bubble)排序:效率 O(n2),適用于排序小列表

? ? * 原理:比較兩個(gè)相鄰的元素跷究,將值大的元素交換至右端。

? ? * 思路:依次比較相鄰的兩個(gè)數(shù),將小數(shù)放在前面,大數(shù)放在后面晕翠。

? ? * 即在第一趟:首先比較第1個(gè)和第2個(gè)數(shù)遍尺,將小數(shù)放前,大數(shù)放后诗祸。

? ? * 然后比較第2個(gè)數(shù)和第3個(gè)數(shù)血久,將小數(shù)放前突照,大數(shù)放后,

? ? * 如此繼續(xù)洋魂,直至比較最后兩個(gè)數(shù),將小數(shù)放前喜鼓,大數(shù)放后副砍。

? ? * 重復(fù)第一趟步驟,直至全部排序完成庄岖。

? ? *

? ? * @param arr

? ? * @return void

????*/

????private static void bubbleSortArray(int[] arr) {

????????int len = arr.length;

? ? ? ? for (int i =1; i < len; i++) {

????????????for (int j =0; j < len - i; j++) {

????????????????if (arr[j] > arr[j +1]) {?//比較交換相鄰元素

? ? ? ? ? ? ? ? ? ? int temp;

? ? ? ? ? ? ? ? ? ? temp = arr[j];

? ? ? ? ? ? ? ? ? ? arr[j] = arr[j +1];

? ? ? ? ? ? ? ? ? ? arr[j +1] = temp;

? ? ? ? ? ? ? ? }

????????????}

????????}

????????System.out.println("冒泡排序結(jié)果:" + Arrays.toString(arr));

????}


????/**

? ? * 選擇排序:效率O(n2)豁翎,適用于排序小的列表

? ? * 原理:每一趟從待排序的記錄中選出最小的元素,順序放在已排好序的序列最后隅忿,直到全部記錄排序完畢心剥。

? ? * 也就是:每一趟在n-i+1(i=1,2背桐,…n-1)個(gè)記錄中選取關(guān)鍵字最小的記錄作為有序序列中第i個(gè)記錄优烧。

? ? * 基于此思想的算法主要有簡(jiǎn)單選擇排序、樹型選擇排序和堆排序链峭。

? ? * 思路:給定數(shù)組 int[] arr={里面n個(gè)數(shù)據(jù)}畦娄;

? ? * 第1趟排序,在待排序數(shù)據(jù)arr[1]~arr[n]中選出最小的數(shù)據(jù)弊仪,將它與arr[1]交換熙卡;

? ? * 第2趟,在待排序數(shù)據(jù)arr[2]~arr[n]中選出最小的數(shù)據(jù)励饵,將它與r[2]交換驳癌;

? ? * 以此類推,第i趟在待排序數(shù)據(jù)arr[i]~arr[n]中選出最小的數(shù)據(jù)役听,將它與r[i]交換颓鲜,直到全部排序完成表窘。

? ? *

? ? * @param arr

? ? * @return void

????*/

? ? private static void selectSortArray(int[] arr) {

????????int len = arr.length;

? ? ? ? int minIndex;

? ? ? ? for (int i =0; i < len -1; i++) {

????????????minIndex = i;

? ? ? ? ? ? for (int j = i +1; j < len; j++) {

????????????????if (arr[j] < arr[minIndex]) minIndex = j; //記下目前找到的最小值所在的位置

????????????}

? ??????????if (minIndex != i) {

????????????????????//找到最小項(xiàng)交換,將這一項(xiàng)移到列表中的正確位置

? ? ? ? ? ? ? ? ? ? int temp;

? ? ? ? ? ? ? ? ? ? temp = arr[i];

? ? ? ? ? ? ? ? ? ? arr[i] = arr[minIndex];

? ? ? ? ? ? ? ? ? ? arr[minIndex] = temp;

? ? ? ? ? ? ? ? }

????????}

????????System.out.println("選擇排序結(jié)果:" + Arrays.toString(arr));

? ? }


????/**

? ? * 插入排序:最佳效率O(n)灾杰;最糟效率O(n2)與冒泡蚊丐、選擇相同,適用于排序小列表 ;若列表基本有序艳吠,則插入排序比冒泡麦备、選擇更有效率。

? ? * 原理:每插入一個(gè)數(shù)都要將它和之前的已經(jīng)完成排序的序列進(jìn)行重新排序昭娩,也就是要找到新插入的數(shù)對(duì)應(yīng)原序列中的位置凛篙。

? ? * 就是說(shuō),每次插入一個(gè)數(shù)都要對(duì)原來(lái)排序好的那部分序列進(jìn)行重新的排序栏渺,時(shí)間復(fù)雜度同樣為O(n2)呛梆。

? ? * 這種算法是穩(wěn)定的排序方法。

? ? *

? ? * @param arr

? ? */

? ? private static void insertSortArray(int[] arr) {

????????int len = arr.length;

? ? ? ? for (int i =1; i < len; i++) {

????????????//循環(huán)從第二個(gè)數(shù)組元素開始磕诊,因?yàn)閍rr[0]作為最初已排序部分

? ? ? ? ? ? int temp = arr[i]; //temp標(biāo)記為未排序第一個(gè)元素

? ? ? ? ? ? int j = i -1;

? ? ? ? ? ? while (j >=0 && arr[j] > temp) {

????????????????//將temp與已排序元素從小到大比較填物,尋找temp應(yīng)插入的位置

? ? ? ? ? ? ? ? arr[j +1] = arr[j];

? ? ? ? ? ? ? ? j--;

? ? ? ? ? ? }

????????????arr[j +1] = temp;

? ? ? ? }

????????System.out.println("插入排序結(jié)果:" + Arrays.toString(arr));

? ? }


????/**

? ? * 希爾排序:縮小增量排序,適用于排序小列表霎终。

? ? * 效率估計(jì)O(nlog2^n)~O(n^1.5)滞磺,取決于增量值的最初大小。

? ? * 建議使用質(zhì)數(shù)作為增量值莱褒,因?yàn)槿绻隽恐凳?的冪击困,則在下一個(gè)通道中會(huì)再次比較相同的元素。

? ? * 希爾排序改進(jìn)了插入排序广凸,減少了比較的次數(shù)阅茶。是不穩(wěn)定的排序,因?yàn)榕判蜻^(guò)程中元素可能會(huì)前后跳躍谅海。

? ? * 思想:先將整個(gè)待排記錄序列分割成為若干子序列分別進(jìn)行直接插入排序脸哀,

? ? * 待整個(gè)序列中的記錄“基本有序”時(shí),在對(duì)全體進(jìn)行一次直接插入排序扭吁。

? ? * 思路:設(shè)待排序元素序列有n個(gè)元素企蹭,首先取一個(gè)整數(shù)increment(小于n)作為間隔將全部元素分為increment個(gè)子序列,

? ? * 所有距離為increment的元素放在同一個(gè)子序列中智末,在每一個(gè)子序列中分別實(shí)行直接插入排序谅摄。

? ? * 然后縮小間隔increment,重復(fù)上述子序列劃分和排序工作系馆。直到最后取increment=1送漠,將所有元素放在同一個(gè)子序列中排序?yàn)橹埂?/p>

? ? * 由于開始時(shí),increment的取值較大由蘑,每個(gè)子序列中的元素較少闽寡,排序速度較快代兵,到排序后期increment取值逐漸變小,

? ? * 子序列中元素個(gè)數(shù)逐漸增多爷狈,由于前面大多數(shù)元素已經(jīng)基本有序植影,所以排序速度仍然很快。

? ? *

? ? * @param arr

? ? */

? ? private static void shellSortArray(int[] arr) {

????????int len = arr.length;

? ? ? ? for (int incr =3; incr >0; incr--) {

????????????//增量遞減涎永,以增量3思币,2,1為例

? ? ? ? ? ? for (int l =0; l < (len -1) / incr; l++) {

????????????????//重復(fù)分成的每個(gè)子列表

? ? ? ? ? ? ? ? for (int i = l + incr; i < len; i += incr) {

????????????????????//對(duì)每個(gè)子列表應(yīng)用插入排序

? ? ? ? ? ? ? ? ? ? int temp = arr[i];

? ? ? ? ? ? ? ? ? ? int j = i - incr;

? ? ? ? ? ? ? ? ? ? while (j >=0 && arr[j] > temp) {

????????????????????????arr[j + incr] = arr[j];

? ? ? ? ? ? ? ? ? ? ? ? j -= incr;

? ? ? ? ? ? ? ? ? ? }

????????????????????arr[j + incr] = temp;

? ? ? ? ? ? ? ? }

????????????}

? ? ? ? }

????????System.out.println("希爾排序結(jié)果:" + Arrays.toString(arr));

? ? }


????/**

? ? * 快速排序:在快速排序中羡微,相等元素可能會(huì)因?yàn)榉謪^(qū)而交換順序谷饿,所以它是不穩(wěn)定的算法。

? ? * 思想:通過(guò)一趟排序?qū)⒁判虻臄?shù)據(jù)分割成獨(dú)立的兩部分:分割點(diǎn)左邊都是比它小的數(shù)妈倔,右邊都是比它大的數(shù)博投。

? ? * 然后再按此方法對(duì)這兩部分?jǐn)?shù)據(jù)分別進(jìn)行快速排序,整個(gè)排序過(guò)程可以遞歸進(jìn)行盯蝴,以此達(dá)到整個(gè)數(shù)據(jù)變成有序序列毅哗。

? ? * 時(shí)間復(fù)雜度:數(shù)據(jù)越隨機(jī)分布時(shí),快速排序性能越好捧挺;數(shù)據(jù)越接近有序虑绵,快速排序性能越差。

? ? * 快速排序的時(shí)間復(fù)雜度在最壞情況下是O(N2)松忍,平均的時(shí)間復(fù)雜度是O(N*lgN)蒸殿。

? ? * 空間復(fù)雜度:快速排序在每次分割的過(guò)程中筷厘,需要1個(gè)空間存儲(chǔ)基準(zhǔn)值鸣峭。而快速排序的大概需要Nlog2N次的分割處理,占用空間也是Nlog2N個(gè)酥艳。

? ? *

? ? * @param arr

? ? * @param left? 數(shù)組的左邊界(例如摊溶,從起始位置開始排序,則left=0)

? ? * @param right 數(shù)組的右邊界(例如充石,排序截至到數(shù)組末尾莫换,則right=a.length-1)

????*/

? ? private static void quickSortArray(int[] arr, int left, int right) {

????????if (left < right) {

????????????int i, j, k;

? ? ? ? ? ? i = left;

? ? ? ? ? ? j = right;

? ? ? ? ? ? k = arr[i];

? ? ? ? ? ? while (i < j) {

????????????????while (i < j && arr[j] > k) j--; //從右向左找第一個(gè)小于k的數(shù)

? ? ? ? ? ? ? ? if (i < j) arr[i++] = arr[j];

? ? ? ? ? ? ? ? while (i < j && arr[i] < k) i++; //從左向右找第一個(gè)大于k的數(shù)

? ? ? ? ? ? ? ? if (i < j) arr[j--] = arr[i];

? ? ? ? ? ? }

????????????arr[j] = k;

? ? ? ? ? ? quickSortArray(arr, left, i -1); //遞歸調(diào)用

? ? ? ? ? ? quickSortArray(arr, i +1, right); //遞歸調(diào)用

? ? ? ? }

????}


????/**

? ? * 歸并排序:

? ? * 思想:將待排序元素分成大小大致相同的2個(gè)子集合,分別對(duì)2個(gè)子集合進(jìn)行排序骤铃,最終將排好序的子集合合并成為所要求的排序集合拉岁。

? ? * @param arr

? ? * @return

? ? */

? ? private static int[]mergeSortArray(int[] arr) {

????????for (int gap =1; gap < arr.length; gap =2 * gap) {

????????????int i =0;

? ? ? ? ? ? // 歸并gap長(zhǎng)度的兩個(gè)相鄰子表

? ? ? ? ? ? for (i =0; i +2 * gap -1 < arr.length; i +=2 * gap)

????????????????merge(arr, i, i + gap -1, i +2 * gap -1);

? ? ? ? ? ? // 余下兩個(gè)子表,后者長(zhǎng)度小于gap

? ? ? ? ? ? if (i + gap -1 < arr.length)

????????????????merge(arr, i, i + gap -1, arr.length -1);

? ? ? ? }

????????return arr;

? ? }

????private static void merge(int[] arr, int low, int mid, int high) {

????????int i = low; // i是第一段序列的下標(biāo)

? ? ? ? int j = mid +1; // j是第二段序列的下標(biāo)

? ? ? ? int k =0; // k是臨時(shí)存放合并序列的下標(biāo)

? ? ? ? int[] arr2 =new int[high - low +1]; //arr2是臨時(shí)合并序列

? ? ? ? // 掃描第一段和第二段序列惰爬,直到有一個(gè)掃描結(jié)束

? ? ? ? while (i <= mid && j <= high) {

????????????// 判斷第一段和第二段取出的數(shù)哪個(gè)更小喊暖,將其存入合并序列,并繼續(xù)向下掃描

? ? ? ? ? ? if (arr[i] <= arr[j]) {

????????????????arr2[k] = arr[i];

? ? ? ? ? ? ? ? i++;

? ? ? ? ? ? ? ? k++;

? ? ? ? ? ? } else {

????????????????arr2[k] = arr[j];

? ? ? ? ? ? ? ? j++;

? ? ? ? ? ? ? ? k++;

? ? ? ? ? ? }

????????}

????????// 若第一段序列還沒(méi)掃描完撕瞧,將其全部復(fù)制到合并序列

? ? ? ? while (i <= mid) {

????????????arr2[k] = arr[i];

? ? ? ? ? ? i++;

? ? ? ? ? ? k++;

? ? ? ? }

????????// 若第二段序列還沒(méi)掃描完陵叽,將其全部復(fù)制到合并序列

? ? ? ? while (j <= high) {

????????????arr2[k] = arr[j];

? ? ? ? ? ? j++;

? ? ? ? ? ? k++;

? ? ? ? }

????????// 將合并序列復(fù)制到原始序列中

? ? ? ? for (k =0, i = low; i <= high; i++, k++) arr[i] = arr2[k];

? ? }

}

運(yùn)行結(jié)果:

冒泡排序結(jié)果:[2, 12, 22, 30, 55, 75, 100, 166, 200]

選擇排序結(jié)果:[2, 12, 22, 30, 55, 75, 100, 166, 200]

插入排序結(jié)果:[2, 12, 22, 30, 55, 75, 100, 166, 200]

希爾排序結(jié)果:[2, 12, 22, 30, 55, 75, 100, 166, 200]

快速排序結(jié)果:[2, 12, 22, 30, 55, 75, 100, 166, 200]

歸并排序結(jié)果:[2, 12, 22, 30, 55, 75, 100, 166, 200]

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末狞尔,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子巩掺,更是在濱河造成了極大的恐慌偏序,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件胖替,死亡現(xiàn)場(chǎng)離奇詭異研儒,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)刊殉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門殉摔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人记焊,你說(shuō)我怎么就攤上這事逸月。” “怎么了遍膜?”我有些...
    開封第一講書人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵碗硬,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我瓢颅,道長(zhǎng)恩尾,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任挽懦,我火速辦了婚禮翰意,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘信柿。我一直安慰自己冀偶,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開白布渔嚷。 她就那樣靜靜地躺著进鸠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪形病。 梳的紋絲不亂的頭發(fā)上客年,一...
    開封第一講書人閱讀 49,185評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音漠吻,去河邊找鬼量瓜。 笑死,一個(gè)胖子當(dāng)著我的面吹牛途乃,可吹牛的內(nèi)容都是我干的绍傲。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼欺劳,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼唧取!你這毒婦竟也來(lái)了铅鲤?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤枫弟,失蹤者是張志新(化名)和其女友劉穎邢享,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體淡诗,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡骇塘,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了韩容。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片款违。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖群凶,靈堂內(nèi)的尸體忽然破棺而出插爹,到底是詐尸還是另有隱情,我是刑警寧澤请梢,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布赠尾,位于F島的核電站,受9級(jí)特大地震影響毅弧,放射性物質(zhì)發(fā)生泄漏气嫁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一够坐、第九天 我趴在偏房一處隱蔽的房頂上張望寸宵。 院中可真熱鬧,春花似錦元咙、人聲如沸梯影。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)光酣。三九已至疏遏,卻和暖如春脉课,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背财异。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工倘零, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人戳寸。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓呈驶,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親疫鹊。 傳聞我的和親對(duì)象是個(gè)殘疾皇子袖瞻,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344