關(guān)于數(shù)組的六種排序

在計(jì)算機(jī)科學(xué)中捻浦,排序是將一串?dāng)?shù)據(jù)按照一定的順序排列起來的算法晤揣。排序算法是解決實(shí)際問題中常用的基本算法之一,應(yīng)用范圍非常廣泛朱灿。

常見的排序算法有冒泡排序昧识、選擇排序、插入排序盗扒、歸并排序跪楞、快速排序缀去、堆排序等等。不同的排序算法有著不同的特點(diǎn)和應(yīng)用場(chǎng)景甸祭,選擇適合的排序算法可以提高程序的效率缕碎。

下面我們就來深入淺出的講解一下幾種排序算法的原理和應(yīng)用,同時(shí)也提供相關(guān)的 TypeScript 代碼實(shí)現(xiàn)池户。

冒泡排序

冒泡排序是一種簡單直觀的排序方法咏雌,它的基本思想是通過不斷比較相鄰的元素,重復(fù)地將大的元素交換到后面校焦,從而逐步將整個(gè)序列排好順序赊抖。

下面是 TypeScript 實(shí)現(xiàn)冒泡排序的代碼:

  const len = arr.length;
  for (let i = 0; i < len - 1; i++) {
    for (let j = 0; j < len - i - 1; j++) {
      if (arr[j] > arr[j + 1]) {
        [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
      }
    }
  }
  return arr;
}

選擇排序

選擇排序的基本思想是每次將未排序序列中最小的元素作為已排序序列的末尾元素。即每次選擇一個(gè)最小的數(shù)放到前面已經(jīng)排序好的序列的最后寨典。

下面是 TypeScript 實(shí)現(xiàn)選擇排序的代碼:

  const len = arr.length;
  let minIndex: number;
  for (let i = 0; i < len - 1; i++) {
    minIndex = i;
    for (let j = i + 1; j < len; j++) {
      if (arr[j] < arr[minIndex]) {
        minIndex = j;
      }
    }
    [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];
  }
  return arr;
}

插入排序

插入排序的基本思想是將未排序序列中的元素插入到已排序序列中的恰當(dāng)位置氛雪,使得插入后的序列仍然有序。

下面是 TypeScript 實(shí)現(xiàn)插入排序的代碼:

  const len = arr.length;
  let preIndex: number, current: number;
  for (let i = 1; i < len; i++) {
    preIndex = i - 1;
    current = arr[i];
    while (preIndex >= 0 && arr[preIndex] > current) {
      arr[preIndex + 1] = arr[preIndex];
      preIndex--;
    }
    arr[preIndex + 1] = current;
  }
  return arr;
}

歸并排序

歸并排序采用分治的思想凝赛,將原序列分成較小的序列注暗,每個(gè)子序列排序后合并成一個(gè)大的有序序列。

下面是 TypeScript 實(shí)現(xiàn)歸并排序的代碼:

function mergeSort(arr: number[]): number[] {
  if (arr.length <= 1) {
    return arr;
  }
  const mid = Math.floor(arr.length / 2);
  const leftArr = arr.slice(0, mid);
  const rightArr = arr.slice(mid);
  return merge(mergeSort(leftArr), mergeSort(rightArr));
}

function merge(left: number[], right: number[]): number[] {
  const res: number[] = [];
  let leftIndex = 0;
  let rightIndex = 0;
  while (leftIndex < left.length && rightIndex < right.length) {
    if (left[leftIndex] < right[rightIndex]) {
      res.push(left[leftIndex]);
      leftIndex++;
    } else {
      res.push(right[rightIndex]);
      rightIndex++;
    }
  }
  return res.concat(left.slice(leftIndex)).concat(right.slice(rightIndex));
}

快速排序

快速排序采用分治的思想墓猎,將原序列分成兩個(gè)子序列捆昏,然后對(duì)子序列排序,最后將兩個(gè)子序列合并成一個(gè)有序序列毙沾。

下面是 TypeScript 實(shí)現(xiàn)快速排序的代碼:

function quickSort(arr: number[]): number[] {
  if (arr.length <= 1) {
    return arr;
  }
  const pivot = arr[0];
  const leftArr: number[] = [];
  const rightArr: number[] = [];
  for (let i = 1; i < arr.length; i++) {
    arr[i] < pivot ? leftArr.push(arr[i]) : rightArr.push(arr[i]);
  }
  return quickSort(leftArr).concat(pivot).concat(quickSort(rightArr));
}

堆排序

堆排序?qū)⒋判蛐蛄袠?gòu)建成一個(gè)大根堆或小根堆骗卜,然后將堆頂元素放到序列的最后,再將剩余元素重新構(gòu)建成一個(gè)堆左胞,重復(fù)上述操作直到整個(gè)序列有序寇仓。

下面是 TypeScript 實(shí)現(xiàn)堆排序的代碼:

function heapSort(arr: number[]): number[] {
  buildHeap(arr);
  for (let i = arr.length - 1; i > 0; i--) {
    swap(arr, 0, i);
    maxHeapify(arr, 0, i - 1);
  }
  return arr;
}

function buildHeap(arr: number[]): void {
  const len = arr.length;
  const lastNode = len - 1;
  const parent = Math.floor((lastNode - 1) / 2);
  for (let i = parent; i >= 0; i--) {
    maxHeapify(arr, i, len - 1);
  }
}

function maxHeapify(arr: number[], start: number, end: number): void {
  let root = start;
  let child = root * 2 + 1;
  while (child <= end) {
    if (child + 1 <= end && arr[child] < arr[child + 1]) {
      child++;
    }
    if (arr[root] < arr[child]) {
      swap(arr, root, child);
      root = child;
      child = root * 2 + 1;
    } else {
      return;
    }
  }
}

function swap(arr: number[], i: number, j: number): void {
  [arr[i], arr[j]] = [arr[j], arr[i]];
}

以上就是六種常見的排序算法以及 TypeScript 實(shí)現(xiàn)代碼。在實(shí)際開發(fā)中烤宙,我們需要根據(jù)不同的應(yīng)用場(chǎng)景選擇不同的排序算法遍烦,從而提高程序的效率。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末躺枕,一起剝皮案震驚了整個(gè)濱河市服猪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌拐云,老刑警劉巖罢猪,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異叉瘩,居然都是意外死亡膳帕,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門薇缅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來危彩,“玉大人攒磨,你說我怎么就攤上這事√裆埃” “怎么了咧纠?”我有些...
    開封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長泻骤。 經(jīng)常有香客問我,道長梧奢,這世上最難降的妖魔是什么狱掂? 我笑而不...
    開封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮亲轨,結(jié)果婚禮上趋惨,老公的妹妹穿的比我還像新娘。我一直安慰自己惦蚊,他們只是感情好器虾,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蹦锋,像睡著了一般兆沙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上莉掂,一...
    開封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天葛圃,我揣著相機(jī)與錄音,去河邊找鬼憎妙。 笑死库正,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的厘唾。 我是一名探鬼主播褥符,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼抚垃!你這毒婦竟也來了喷楣?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤讯柔,失蹤者是張志新(化名)和其女友劉穎抡蛙,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體魂迄,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡粗截,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了捣炬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片熊昌。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡绽榛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出婿屹,到底是詐尸還是另有隱情灭美,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布昂利,位于F島的核電站届腐,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏蜂奸。R本人自食惡果不足惜犁苏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望扩所。 院中可真熱鬧围详,春花似錦、人聲如沸祖屏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽袁勺。三九已至雹食,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間魁兼,已是汗流浹背婉徘。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留咐汞,地道東北人盖呼。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像化撕,于是被迫代替她去往敵國和親几晤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

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