數(shù)據(jù)結(jié)構(gòu)與算法

大O符號(hào):Big O notation离福,是由德國(guó)數(shù)論學(xué)家保羅·巴赫曼在其1892年的著作《解析數(shù)論》首先引入的
指數(shù)函數(shù):冪 = 2N
對(duì)數(shù)函數(shù):指數(shù) = log2N,log10N簡(jiǎn)寫(xiě)為lgN炼蛤,logeN簡(jiǎn)寫(xiě)為lnN
對(duì)數(shù)的底:logaN中妖爷,增長(zhǎng)率主要取決于N,因此O(logaN)簡(jiǎn)寫(xiě)為O(logN)
平均時(shí)間復(fù)雜度:常數(shù) c理朋、對(duì)數(shù) logN絮识、對(duì)數(shù)平方log2N、線性N嗽上、NlogN次舌、平方N2、指數(shù) 2N

鏈表 List
ArrayList:數(shù)組實(shí)現(xiàn)兽愤,查找和更新 O(c)彼念,添加和刪除 O(N)
LinkedList:雙鏈表實(shí)現(xiàn),查找和更新 O(N)浅萧,添加和刪除 O(c)

棧 Stack
可以把雙鏈表當(dāng)做棧來(lái)操作逐沙,即后進(jìn)先出

隊(duì)列 Queue
可以把雙鏈表當(dāng)做隊(duì)列來(lái)操作,即先進(jìn)先出

樹(shù)

樹(shù)的遍歷
先序遍歷:先處理本節(jié)點(diǎn)惯殊,再處理子節(jié)點(diǎn)
中序遍歷:先處理左子樹(shù)酱吝,在處理本節(jié)點(diǎn),最后處理由子樹(shù)
后序遍歷:先處理子節(jié)點(diǎn)土思,再處理本節(jié)點(diǎn)

二叉樹(shù)
每個(gè)枝節(jié)點(diǎn)最多有兩個(gè)子節(jié)點(diǎn)务热,二叉樹(shù)的平均高度為O(√N(yùn)),N為節(jié)點(diǎn)數(shù)

二叉查找樹(shù)
每個(gè)枝節(jié)點(diǎn)己儒,它的左子節(jié)點(diǎn)小于它崎岂,它的右子節(jié)點(diǎn)大于它
二叉查找樹(shù)的節(jié)點(diǎn)的平均高度為O(logN),即查找闪湾、新增的平均時(shí)間為O(logN)冲甘,最壞O(n)
二叉查找樹(shù)節(jié)點(diǎn)刪除:刪除A節(jié)點(diǎn)的左子節(jié)點(diǎn)B,則查找B節(jié)點(diǎn)的右子樹(shù)的最小節(jié)點(diǎn)C,來(lái)替換B江醇。如果C不是葉節(jié)點(diǎn)濒憋,則遞歸刪除。
懶惰刪除:不實(shí)際刪除節(jié)點(diǎn)陶夜,而是標(biāo)記為假刪除

AVL樹(shù)(取名于兩個(gè)發(fā)明者名字的首字母)
帶有平衡條件的二叉查找樹(shù)凛驮,保證每個(gè)節(jié)點(diǎn)的左子樹(shù)和右子樹(shù)的高度最多差1
實(shí)現(xiàn):A有左子節(jié)點(diǎn)B,沒(méi)有右子節(jié)點(diǎn)条辟,要給B插入左子節(jié)點(diǎn)C黔夭,會(huì)導(dǎo)致A失衡。讓B代替A的位置羽嫡,A作為B的右子節(jié)點(diǎn)本姥。最終為B有左子節(jié)點(diǎn)C,右子節(jié)點(diǎn)A

B樹(shù)(Balanced Tree of Order M杭棵,多叉平衡搜索樹(shù))
1婚惫、葉節(jié)點(diǎn)是個(gè)數(shù)組,數(shù)據(jù)項(xiàng)只保存在葉節(jié)點(diǎn)的數(shù)組中
2魂爪、枝節(jié)點(diǎn)保存兩組數(shù)據(jù)辰妙,形如[100,200] [子節(jié)點(diǎn)1,子節(jié)點(diǎn)2甫窟,子節(jié)點(diǎn)3]
3密浑、子節(jié)點(diǎn)1的數(shù)據(jù)范圍在(,100],子節(jié)點(diǎn)2的數(shù)據(jù)范圍在[100,200]粗井,子節(jié)點(diǎn)3的數(shù)據(jù)范圍在[200,)

紅黑樹(shù)
帶有顏色標(biāo)記的二叉查找樹(shù)尔破,get\add\remove的最壞時(shí)間復(fù)雜度O(logN)
1、每個(gè)節(jié)點(diǎn)要么是紅色浇衬,要么是黑色懒构。根節(jié)點(diǎn)是黑色
2、紅色節(jié)點(diǎn)不能連續(xù)
3耘擂、任一節(jié)點(diǎn)胆剧,向下到樹(shù)末梢的任何路徑,都含有相同個(gè)數(shù)的黑色節(jié)點(diǎn)
與二叉查找樹(shù)對(duì)比:任一子樹(shù)的最長(zhǎng)路徑不大于最短路徑的兩倍醉冤,保證了查找速度
與AVL樹(shù)對(duì)比:降低了平衡條件秩霍,任何不平衡都會(huì)在三次旋轉(zhuǎn)之內(nèi)解決,使得插入和刪除的性能更高

散列

散列三要素
散列函數(shù):輸入key蚁阳,輸出一個(gè)散列值铃绒,例如取余函數(shù)
散列表:存放數(shù)據(jù)的空間
散列沖突解決方案:解決多條數(shù)據(jù)的散列值相同的問(wèn)題

分離鏈接法(拉鏈法):把散列值相同的數(shù)據(jù)放到鏈表中
線性探測(cè)法:一條數(shù)據(jù)在散列表上的位置已經(jīng)被占據(jù),則把他放到下一個(gè)存儲(chǔ)單元
雙散列:一條數(shù)據(jù)在散列表上的位置已經(jīng)被占據(jù)螺捐,則把它放到2倍散列值的位置上

JAVA里的散列實(shí)現(xiàn)
數(shù)組作為散列表颠悬,數(shù)組的一項(xiàng)作為桶矮燎,拉鏈法解決散列沖突。hashCode()相同的放入一個(gè)桶赔癌,hashCode()相同并equals()的诞外,當(dāng)做重復(fù)元素。數(shù)組有一個(gè)初始長(zhǎng)度灾票,數(shù)據(jù)量到達(dá)閾值時(shí)浅乔,擴(kuò)容resize到原來(lái)的兩倍,并重新散列rehash铝条。除非發(fā)生擴(kuò)容,否則操作時(shí)間復(fù)雜度O(1)席噩,比紅黑樹(shù)快班缰。
以HashMap為例,構(gòu)造時(shí)可以傳入兩個(gè)參數(shù)initialCapacity和loadFactor悼枢,即初始容量和擴(kuò)容閾值埠忘,默認(rèn)為16和0.75。最佳初始容量為 預(yù)期數(shù)據(jù)量 / loadFactor + 1馒索。

無(wú)重復(fù)集合 Set
TreeSet:紅黑樹(shù)實(shí)現(xiàn)莹妒,有序,元素需要實(shí)現(xiàn)Comparable接口的compareTo方法绰上,不能放入null
HashSet:散列實(shí)現(xiàn)旨怠,可以放入一個(gè)null
LinkedHashSet:散列表存放數(shù)據(jù),鏈表記錄插入順序蜈块,順序與TreeSet不同

映射 Map
TreeMap:紅黑樹(shù)實(shí)現(xiàn)
HashMap:散列實(shí)現(xiàn)鉴腻,key、value都可以為null百揭。
Hashtable:散列實(shí)現(xiàn)爽哎,key、value都不可以為null器一。每個(gè)操作方法都聲明了Synchronize课锌,線程安全,同時(shí)性能也稍低祈秕。
ConcurrentHashMap:散列實(shí)現(xiàn)渺贤,線程安全,迭代時(shí)只鎖死部分元素请毛,比Hashtable性能稍高

優(yōu)先隊(duì)列 priority queue
優(yōu)先隊(duì)列通常用二叉堆來(lái)實(shí)現(xiàn)癣亚,因此二叉堆可以指代優(yōu)先隊(duì)列,簡(jiǎn)稱堆

二叉堆 binary heap
完全二叉樹(shù):除了最后兩層获印,所有節(jié)點(diǎn)都有兩個(gè)子節(jié)點(diǎn)述雾,且最底層節(jié)點(diǎn)從左到右緊密排列街州。可以用樹(shù)實(shí)現(xiàn)玻孟,可一樣用數(shù)組實(shí)現(xiàn)唆缴。
二叉堆:一個(gè)完全二叉樹(shù),它的每棵子樹(shù)的根節(jié)點(diǎn)都是這個(gè)子樹(shù)的最小元素
PriorityQueue:數(shù)組式二叉堆實(shí)現(xiàn)

排序(以下排序說(shuō)的都是升序)

雙循環(huán)法

冒泡排序 平均O(n2)黍翎,最壞O(n2)

// 任一時(shí)刻面徽,數(shù)組的后部分已排好序
for (var i = 0; i < len; i++) {
 for (var j = 0; j < len - i - 1; j++) {   // 遍歷前部分
  if (arr[j] > arr[j+1]) {                   // 對(duì)比相鄰元素,讓大元素往后冒泡匣掸,加入到后部分
   var temp = arr[j+1];  
   arr[j+1] = arr[j];
   arr[j] = temp;
  }
 }
}

選擇排序 平均O(n2)趟紊,最壞O(n2)

var len = arr.length;
// 任一時(shí)刻,數(shù)組的前部分已排好序
for (var i = 0; i < len - 1; i++) {
 var minIndex = i;
 for (var j = i + 1; j < len; j++) {  // 遍歷后部分碰酝,找到最小值
  if (arr[j] < arr[minIndex]) {
    minIndex = j; 
  }
 }
 var temp = arr[i];                   // 把找到的最小值加到前部分
 arr[i] = arr[minIndex];
 arr[minIndex] = temp;
}

插入排序 平均O(n2)霎匈,最壞O(n2)

// 任一時(shí)刻,數(shù)組的前部分已排好序
for (var i = 1; i < array.length; i++) {
 var cur = array[i];
 for(var j=i-1; array[ j ] > cur; j-- ) {    // 從后往前遍歷前部分送爸,將當(dāng)前元素插入到前部分
   array[ j + 1] = array[ j ];            // 比當(dāng)前元素大的都往后移動(dòng)一格
 }
 array[ j + 1] = cur;      // 將當(dāng)前元素插入
}
分組法

希爾排序 平均O(nlogn)铛嘱,最壞O(nlog2n)

var len = arr.length, gap = 1;
while(gap < len / 5) {  // 動(dòng)態(tài)定義初始間隔
  gap =gap*5+1;    // 此計(jì)算為實(shí)踐經(jīng)驗(yàn),gap和length的關(guān)系為 [1,1-5] [6, 6-30] [31, 31-155]
}
while (gap > 0) {
   // 位置相差gap的元素分為一組袭厂,對(duì)每組進(jìn)行插入排序
 for (var i = gap; i < len; i++) {  // i 每加1墨吓,就進(jìn)入到了另外一組,所以對(duì)每組的排序 是 穿插進(jìn)行的
  var temp = arr[i];
  for (var j = i-gap; j >= 0 && arr[ j ] > temp; j-=gap) {
   arr[ j+gap ] = arr[ j ];
  }
  arr[ j+gap ] = temp;
 }
    gap = Math.floor(gap / 5);  // gap最后一次是 1纹磺,就是一個(gè)插入排序帖烘,但此時(shí)元素移動(dòng)可以大大減少
}

歸并排序 平均O(nlog n),最壞O(nlog n)

function mergeSort(arr) {
  var len = arr.length;
  if(len < 2) {      // 拆分到只有一個(gè)元素時(shí)橄杨,就當(dāng)做是排好序的數(shù)組
    return arr;
  }
  var middle = Math.floor(len / 2),   // 把數(shù)組拆分成兩半
  left = mergeSort(arr.slice(0, middle)), 
  right = mergeSort(arr.slice(middle));  // 兩半分別排好序
  return merge(left, right);   // 將排好序的兩半進(jìn)行歸并
}
function merge(left, right){
  var result = [];
  while (left.length && right.length) {
    if (left[0] <= right[0]) {
      result.push(left.shift());
    } else {
      result.push(right.shift());
    }
  }
  while (left.length){
    result.push(left.shift());
  }
  while (right.length){
    result.push(right.shift());
  }
  return result;
}

快速排序 平均O(n*log n)蚓让,最壞O(n2)

function quickSort(array, start, end) {
  if (start < end) {       // 當(dāng) start 等于end 時(shí),就是拆分到了一個(gè)元素
    var last = array[end],          // 用最后一個(gè)元素 跟 其他元素比較
                    i = start - 1;                   // 標(biāo)記比last小的元素存放的位置讥珍,目前還沒(méi)有历极,所以是 -1
    for (var j = start; j <= end; j++) {   // 遍歷整個(gè)數(shù)組
      if (array[ j ] <= last ) {   // 當(dāng)前元素小于等于last,則交換到位置 i
        i++;
        var temp = array[ i ];
        array[ i ] = array[ j ];
        array[ j ] = temp;
      }
    }
              // 將數(shù)組拆分成兩個(gè)數(shù)組衷佃,分別排序趟卸,其中一個(gè)數(shù)組都小于等于last,另一個(gè)都大于last 
    quickSort(array, start, i - 1);  // start 到 i - 1都小于等于last
              // 中間還有個(gè)array[ i ]就是 last
    quickSort(array, i + 1, end);  // i + 1到end都大于last
  }
  return array;
}
quickSort(arr,0,arr.length-1);
分桶法

以下k表示桶數(shù)

計(jì)數(shù)排序 平均O(n+k)氏义,最壞O(n+k)
把數(shù)據(jù)的值作為下標(biāo)锄列,放到一個(gè)新數(shù)組中,最后只要順次讀取新數(shù)組
限制:桶的數(shù)量(新數(shù)組的長(zhǎng)度)不小于數(shù)據(jù)的取值范圍

桶排序 平均O(n+k)惯悠,最壞O(n2)
1邻邮、遍歷數(shù)組,將相同級(jí)別的數(shù)據(jù)放到一個(gè)桶中
2克婶、分別排序每一個(gè)桶
3筒严、讀出每一個(gè)桶的數(shù)據(jù)
例如:100以內(nèi)數(shù)字的排序丹泉,根據(jù)數(shù)字的十位數(shù),分別放到編號(hào)0-9的數(shù)組中鸭蛙,分別對(duì)每個(gè)數(shù)組排序摹恨,依次讀出每個(gè)桶里的數(shù)字

基數(shù)排序 平均O(nk),最壞O(nk)
1娶视、遍歷數(shù)組晒哄,將相同尾數(shù)的數(shù)據(jù)放到一個(gè)桶中
2、按順序讀出所有數(shù)據(jù)肪获,再根據(jù)次尾數(shù)分別放到桶中寝凌,以此類推
3、按順序讀出所有數(shù)據(jù)
例如:對(duì)[12,11,2,1]排序孝赫,放入兩個(gè)桶[11,1][12,2]较木,讀出[11,1,12,2],再次入桶[1,2][11,12]寒锚,再次讀出[1,2,11,12]

二叉樹(shù)法

堆排序 平均O(nlog n),最壞O(nlog n)
即每次從二叉堆中取出堆頂元素

常見(jiàn)問(wèn)題與方案

topK

問(wèn)題:從N個(gè)數(shù)中违孝,找到最大的K個(gè)數(shù)
方案:讀取前K個(gè)數(shù)刹前,創(chuàng)建一個(gè)堆頂為最小數(shù)的堆;讀取后N-K個(gè)數(shù)雌桑,比堆頂大則刪除堆頂喇喉,并插入堆;時(shí)間復(fù)雜度為O(N*logK)

尋找中位數(shù)

等同于找出 top N/2

一個(gè)整數(shù)的二進(jìn)制表示中1的個(gè)數(shù)

while(n>0){
if((n&1)==1){result++}
n = n>>1 // 每次消除一位
}

while(n>0){
result ++;
n = n&(n-1) // 每次消除一個(gè)1
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末校坑,一起剝皮案震驚了整個(gè)濱河市拣技,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌耍目,老刑警劉巖膏斤,帶你破解...
    沈念sama閱讀 218,451評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異邪驮,居然都是意外死亡莫辨,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)毅访,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)沮榜,“玉大人,你說(shuō)我怎么就攤上這事喻粹◇∪冢” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,782評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵守呜,是天一觀的道長(zhǎng)型酥。 經(jīng)常有香客問(wèn)我山憨,道長(zhǎng),這世上最難降的妖魔是什么冕末? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,709評(píng)論 1 294
  • 正文 為了忘掉前任萍歉,我火速辦了婚禮,結(jié)果婚禮上档桃,老公的妹妹穿的比我還像新娘枪孩。我一直安慰自己,他們只是感情好藻肄,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布蔑舞。 她就那樣靜靜地躺著,像睡著了一般嘹屯。 火紅的嫁衣襯著肌膚如雪攻询。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,578評(píng)論 1 305
  • 那天州弟,我揣著相機(jī)與錄音钧栖,去河邊找鬼。 笑死婆翔,一個(gè)胖子當(dāng)著我的面吹牛拯杠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播啃奴,決...
    沈念sama閱讀 40,320評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼潭陪,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了最蕾?” 一聲冷哼從身側(cè)響起依溯,我...
    開(kāi)封第一講書(shū)人閱讀 39,241評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瘟则,沒(méi)想到半個(gè)月后黎炉,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,686評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡醋拧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評(píng)論 3 336
  • 正文 我和宋清朗相戀三年拜隧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片趁仙。...
    茶點(diǎn)故事閱讀 39,992評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡洪添,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出雀费,到底是詐尸還是另有隱情干奢,我是刑警寧澤,帶...
    沈念sama閱讀 35,715評(píng)論 5 346
  • 正文 年R本政府宣布盏袄,位于F島的核電站忿峻,受9級(jí)特大地震影響薄啥,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜逛尚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評(píng)論 3 330
  • 文/蒙蒙 一垄惧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧绰寞,春花似錦到逊、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,912評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至件缸,卻和暖如春铜靶,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背他炊。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,040評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工争剿, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人痊末。 一個(gè)月前我還...
    沈念sama閱讀 48,173評(píng)論 3 370
  • 正文 我出身青樓蚕苇,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親舌胶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子捆蜀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評(píng)論 2 355

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

  • 數(shù)據(jù)結(jié)構(gòu)學(xué)科的定義:主要是為研究和解決如何使用計(jì)算機(jī)處理非數(shù)值問(wèn)題而產(chǎn)生的理論疮丛、技術(shù)和方法幔嫂。數(shù)據(jù)結(jié)構(gòu):是相互之間存...
    冷了年度閱讀 1,591評(píng)論 0 0
  • 前言 上一篇《數(shù)據(jù)結(jié)構(gòu)和算法》中我介紹了數(shù)據(jù)結(jié)構(gòu)的基本概念,也介紹了數(shù)據(jù)結(jié)構(gòu)一般可以分為邏輯結(jié)構(gòu)和物理結(jié)構(gòu)誊薄。邏輯結(jié)...
    VV木公子閱讀 4,663評(píng)論 4 41
  • 算法引入:如果a+b+c=1000履恩,且a2+b2=c^2(a,b,c為自然數(shù)),如何求出所有a呢蔫,b切心,c可能的組合?...
    Bling_ll閱讀 510評(píng)論 0 3
  • 印度有四句極具靈性的話: 無(wú)論你遇見(jiàn)誰(shuí)片吊,他都是對(duì)的人绽昏; 無(wú)論發(fā)生什么事,那都是唯一會(huì)發(fā)生的事俏脊; 不管事情開(kāi)始于哪個(gè)...
    李思睿vicky閱讀 1,188評(píng)論 0 1
  • 上次分手改了名字全谤。兩年心里很執(zhí)拗。現(xiàn)在放棄了爷贫。由于今天早上公交司機(jī)的話认然。還有昨天补憾。所以。不好意思對(duì)不起卷员。 工作的事...
    0401閱讀 439評(píng)論 0 0