各種排序算法的Java實(shí)現(xiàn)

二分查找

又叫折半查找浇冰,要求待查找的序列有序。每次取中間位置的值與待查關(guān)鍵字比較洋魂,如果中間位置的值比待查關(guān)鍵字大槐秧,則在前半部分循環(huán)這個查找的過程,如果中間位置的值比待查關(guān)鍵字小忧设,則在后半部分循環(huán)這個查找的過程刁标。直到查找到了為止,否則序列中沒有待查的關(guān)鍵字

public static int biSearch(int[] array, int a) {

????int lo =0;

? ? int hi = array.length -1;

? ? int mid;

? ? while (lo <= hi) {

mid = (lo + hi) /2;//中間位置

? ? ? ? if (array[mid] == a) {

return mid;

? ? ? ? }else if (array[mid] < a) {//向右查找

? ? ? ? ? ? lo = mid +1;

? ? ? ? }else {//向左查找

? ? ? ? ? ? hi = mid -1;

? ? ? ? }

}

return -1;

}

冒泡排序算法

(1)比較前后相鄰的二個數(shù)據(jù)址晕,如果前面數(shù)據(jù)大于后面的數(shù)據(jù)膀懈,就將這二個數(shù)據(jù)交換。

(2)這樣對數(shù)組的第 0 個數(shù)據(jù)到 N-1 個數(shù)據(jù)進(jìn)行一次遍歷后谨垃,最大的一個數(shù)據(jù)就“沉”到數(shù)組第N-1 個位置启搂。

(3)N=N-1硼控,如果 N 不為 0 就重復(fù)前面二步,否則排序完成

public static void bubbleSort(int[] a, int n) {

? ? int i, j;

? ? for (i =0; i < n; i++) {

????????for (j =1; j < n - i; j++) {

????????????if (a[j -1] > a[j]) {

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

? ? ? ? ? ? ? ? temp = a[j -1];

? ? ? ? ? ? ? ? a[j -1] = a[j];

? ? ? ? ? ? ? ? a[j] = temp;

? ? ? ? ? ? }

}

}

}

插入排序算法

通過構(gòu)建有序序列胳赌,對于未排序數(shù)據(jù)牢撼,在已排序序列中從后向前掃描,找到相應(yīng)的位置并插入疑苫。插入排序非常類似于整撲克牌熏版。在開始摸牌時,左手是空的捍掺,牌面朝下放在桌上撼短。接著,一次從桌上摸起一張牌挺勿,并將它插入到左手一把牌中的正確位置上曲横。為了找到這張牌的正確位置,要將它與手中已有的牌從右到左地進(jìn)行比較不瓶。無論什么時候禾嫉,左手中的牌都是排好序的。如果輸入數(shù)組已經(jīng)是排好序的話蚊丐,插入排序出現(xiàn)最佳情況夭织,其運(yùn)行時間是輸入規(guī)模的一個線性函數(shù)。如果輸入數(shù)組是逆序排列的吠撮,將出現(xiàn)最壞情況。平均情況與最壞情況一樣讲竿,其時間代價是(n2)泥兰。

public static void insertSort(int[] a) {

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

????????int insertVal = a[i];//插入的數(shù)

? ? ? ? int index = i -1;//被插入的位置(準(zhǔn)備和前一個數(shù)比較)

? ? ? ? //如果插入的數(shù)比被插入的數(shù)小

? ? ? ? while (index >=0 && insertVal < a[index]) {

????????????//將把a(bǔ)[index]向后移動

? ? ? ? ? ? a[index +1] = a[index];

? ? ? ? ? ? //讓index向前移動

? ? ? ? ? ? index--;

? ? ? ? }

????????//把插入的數(shù)放入合適的位置

? ? ? ? a[index +1] = insertVal;

? ? }

}

快速排序算法

快速排序的原理:選擇一個關(guān)鍵值作為基準(zhǔn)值。比基準(zhǔn)值小的都在左邊序列(一般是無序的)题禀,比基準(zhǔn)值大的都在右邊(一般是無序的)鞋诗。一般選擇序列的第一個元素。一次循環(huán):從后往前比較迈嘹,用基準(zhǔn)值和最后一個值比較削彬,如果比基準(zhǔn)值小的交換位置,如果沒有繼續(xù)比較下一個秀仲,直到找到第一個比基準(zhǔn)值小的值才交換融痛。找到這個值之后,又從前往后開始比較神僵,如果有比基準(zhǔn)值大的雁刷,交換位置,如果沒有繼續(xù)比較下一個保礼,直到找到第一個比基準(zhǔn)值大的值才交換沛励。直到從前往后的比較索引>從后往前比較的索引责语,結(jié)束第一次循環(huán),此時目派,對于基準(zhǔn)值來說坤候,左右兩邊就是有序的了

public static void quickSort(int[] arr, int low, int high) {

????int i, j, key, t;

? ? if (low > high) {

????????return;

? ? }

????i = low;

? ? j = high;

? ? //key就是基準(zhǔn)位

? ? key = arr[low];

? ? while (i < j) {

????????//先看右邊,依次往左遞減

? ? ? ? while (key <= arr[j] && i < j) {

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

? ? ? ????? }

????????//再看左邊企蹭,依次往右遞增

? ? ? ? while (key >= arr[i] && i < j) {

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

? ? ? ? }

????????//如果滿足條件則交換

? ? ? ? if (i < j) {

????????????t = arr[j];

? ? ? ? ? ? arr[j] = arr[i];

? ? ? ? ? ? arr[i] = t;

? ? ? ? }

}

????//最后將基準(zhǔn)為與i和j相等位置的數(shù)字交換

? ? arr[low] = arr[i];

? ? arr[i] = key;

? ? //此時第一次循環(huán)比較結(jié)束白筹,關(guān)鍵值的位置已經(jīng)確定了。左邊的值都比關(guān)鍵值小练对,右邊的

? ? //值都比關(guān)鍵值大遍蟋,但是兩邊的順序還有可能是不一樣的,進(jìn)行下面的遞歸調(diào)用

? ? //遞歸調(diào)用左半數(shù)組

? ? quickSort(arr, low, j -1);

? ? //遞歸調(diào)用右半數(shù)組

? ? quickSort(arr, j +1, high);

}


希爾排序算法

基本思想:先將整個待排序的記錄序列分割成為若干子序列分別進(jìn)行直接插入排序螟凭,待整個序列

中的記錄“基本有序”時虚青,再對全體記錄進(jìn)行依次直接插入排序。

1. 操作方法: 選擇一個增量序列 t1螺男,t2棒厘,…,tk下隧,其中 ti>tj奢人,tk=1;

2. 按增量序列個數(shù) k淆院,對序列進(jìn)行 k 趟排序何乎;

3. 每趟排序,根據(jù)對應(yīng)的增量 ti土辩,將待排序列分割成若干長度為 m 的子序列支救,分別對各子表進(jìn)行直接插入排序。僅增量因子為1 時拷淘,整個序列作為一個表來處理各墨,表長度即為整個序列的長度。

public static void shellSort(int[] a) {

????int dk = a.length /2;

? ? while (dk >=1) {

????????ShellInsertSort(a, dk);

? ? ? ? dk = dk /2;

? ? }

}

public static void ShellInsertSort(int[] a, int dk) {

//類似插入排序启涯,只是插入排序增量是 1贬堵,這里增量是 dk,把 1 換成 dk 就可以了

? ? for (int i = dk; i < a.length; i++) {

????????if (a[i] < a[i - dk]) {

????????????int j;

? ? ? ? ? ? int x = a[i];//x 為待插入元素

? ? ? ? ? ? a[i] = a[i - dk];

? ? ? ? ? ? for (j = i - dk; j >=0 && x < a[j]; j = j - dk) {

????????????????//通過循環(huán),逐個后移一位找到要插入的位置结洼。

? ? ? ? ? ? ? ? a[j + dk] = a[j];

? ? ? ? ? ? }

????????????????a[j + dk] = x;//插入

? ? ? ? }

}

}

歸并排序算法

歸并(Merge)排序法是將兩個(或兩個以上)有序表合并成一個新的有序表黎做,即把待排序序列分為若干個子序列,每個子序列是有序的松忍。然后再把有序子序列合并為整體有序序列引几。

public class MergeSortTest {

????public static void main(String[] args) {

????????int[] data = new int[] { 5, 3, 6, 2, 1, 9, 4, 8, 7 };

????????print(data);

????????mergeSort(data);

????????System.out.println("排序后的數(shù)組:");

????????print(data);

}

public static void mergeSort(int[] data) {

????????sort(data, 0, data.length - 1);

}

public static void sort(int[] data, int left, int right) {

????if (left >= right)

????????return;

????// 找出中間索引

????int center = (left + right) / 2;

????// 對左邊數(shù)組進(jìn)行遞歸

????sort(data, left, center);

????// 對右邊數(shù)組進(jìn)行遞歸

????sort(data, center + 1, right);

????// 合并

????merge(data, left, center, right);

????print(data);

}

/**

* 將兩個數(shù)組進(jìn)行歸并,歸并前面 2 個數(shù)組已有序,歸并后依然有序*

* @param data 數(shù)組對象

* @param left 左數(shù)組的第一個元素的索引

* @param center 左數(shù)組的最后一個元素的索引伟桅,center+1 是右數(shù)組第一個元素的索引

* @param right 右數(shù)組最后一個元素的索引

*/

public static void merge(int[] data, int left, int center, int right) {

????// 臨時數(shù)組

????int[] tmpArr = new int[data.length];

????// 右數(shù)組第一個元素索引

????int mid = center + 1;

????// third 記錄臨時數(shù)組的索引

????int third = left;

????// 緩存左數(shù)組第一個元素的索引

????int tmp = left;

????while (left <= center && mid <= right) {

????????// 從兩個數(shù)組中取出最小的放入臨時數(shù)組

????????if (data[left] <= data[mid]) {

????????????tmpArr[third++] = data[left++];

????????} else {

????????????tmpArr[third++] = data[mid++];

????}

}

????// 剩余部分依次放入臨時數(shù)組(實(shí)際上兩個 while 只會執(zhí)行其中一個)

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

????tmpArr[third++] = data[mid++];

????}

????while (left <= center) {

????tmpArr[third++] = data[left++];

}

// 將臨時數(shù)組中的內(nèi)容拷貝回原數(shù)組中

// (原 left-right 范圍的內(nèi)容被復(fù)制回原數(shù)組)

????while (tmp <= right) {

????????data[tmp] = tmpArr[tmp++];

????}

}

public static void print(int[] data) {

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

????System.out.print(data[i] + "\t");

????}

????System.out.println();

}

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末敞掘,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子楣铁,更是在濱河造成了極大的恐慌玖雁,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盖腕,死亡現(xiàn)場離奇詭異赫冬,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)溃列,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進(jìn)店門劲厌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人听隐,你說我怎么就攤上這事补鼻。” “怎么了雅任?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵风范,是天一觀的道長。 經(jīng)常有香客問我沪么,道長硼婿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任禽车,我火速辦了婚禮寇漫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘殉摔。我一直安慰自己州胳,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布钦勘。 她就那樣靜靜地躺著,像睡著了一般亚亲。 火紅的嫁衣襯著肌膚如雪彻采。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天捌归,我揣著相機(jī)與錄音肛响,去河邊找鬼。 笑死惜索,一個胖子當(dāng)著我的面吹牛特笋,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼猎物,長吁一口氣:“原來是場噩夢啊……” “哼虎囚!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蔫磨,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤淘讥,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后堤如,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蒲列,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年搀罢,在試婚紗的時候發(fā)現(xiàn)自己被綠了蝗岖。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡榔至,死狀恐怖抵赢,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情洛退,我是刑警寧澤瓣俯,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站兵怯,受9級特大地震影響彩匕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜媒区,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一驼仪、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧袜漩,春花似錦绪爸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至座掘,卻和暖如春递惋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背溢陪。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工萍虽, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人形真。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓杉编,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子邓馒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評論 2 354

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