資料結構

Data Structure

Today's Topic 按照長相分類







樹狀資料結構

Heap

Map

Set

Disjoint Set

Queue

陣列資料結構

Array

Stack

Deque

Linked-list

Vector

Today's Topic


按重要性排序

Heap

Stack

Queue

Vector

Disjoint Set

Deque



沒有蠢問題!!!



Q

為甚麼重要性排行榜沒有Set?


A

因為我不會用

GoGo! >>>



從Array開始說起...

陣列很Open




但是你無法方便的掌握他

For example




從最尾端往前遍歷 --> len 維護O(1)

當前最大值 --> 維護O(N)

找某項元素 --> O(N) or O(lgN)


總之就是很麻煩

包裝很重要



於是我們想到...


Item 丟進去--> 神秘資料結構

Item 丟進去--> 神秘資料結構

item 丟進去--> 神秘資料結構


然後結果就出來了!!!

換一個說法


一個資料結構會維護一個特性


有一些操作破壞這個特性


然後我們再想辦法經由固定的手段把特性弄回來

沒有蠢問題!! 再談資料結構


Q

所以神秘資料結構要有甚麼



A

提供限定的操作(For you, For me)

維護你想知道的資訊

GOGO!!!!-->



--->


-->


-->



STACK & QUEUE

STACK



STACK <-- ITEM

STACK --> ITEM


從哪裡丟進去 從哪裡拿出來


也可以說是

[先進 後出]

Stack


   push(1) --> 1
      push(2) --> 1,2
          push(3) --> 1,2,3
pop() --> 3
pop() --> 2
pop() --> 1

QUEUE



ITEM --> QUEUE

QUEUE --> ITEM


從左邊丟進去 從另一邊拿出來

也可以說是

先進先出 = 排隊

Queue


push(1) -> 1
push(2) -> 1 2
push(3) -> 1 2 3
pop() -> 1
pop() -> 2
pop() -> 3

Deque


雖然不是很重要


ITEM --> Deque --> ITEM

ITEM <-- Deque <-- ITEM


順帶一提
C++的Queue是用Deque做的。

沒有蠢問題!!

所以這三個結構想「維護」甚麼?


Stack

保存最初的資料


Queue

資料的順序性


Deque

結合以上兩者(這是屁話)

通常拿來維護單調性(遞增or遞減)

Stack & Queue




特別的 他們被拿來做DFS跟BFS

(資料的遍歷)


DFS&BFS
下一堂會講 <3



STACK

stack的操作


push 把元素丟到最上層

top 讀取最上層元素

pop 丟掉最上層元素

Stack 與單調性維護

你養了 n 頭高矮不一定相同的乳牛,某天你叫他們由左到右排成一列。


乳牛們習慣向右邊看,每頭乳牛可以往右看到無限遠的地方,直到第一隻大於等於自己身高的牛擋住自己視線為止。

由左到右數的第 i 隻乳牛可以看到右邊的 Ci 隻乳牛(不包含自己),你希望求出所有 Ci 的總和。
ex
身高 = 2  3  1
     Ci = 1  1  0
sum = 2


ex
身高 = 4  2  3  1
     Ci = 3 1  1  0
sum = 5

ex
身高 = 3  2  1
     Ci = 2  1  0
sum = 3

這題要做甚麼阿囧!


找到誰會最先擋住他的視線!!!

for(int i=1;i<N;i++){
    int j = i+1;
    while(j <= N){
         if(high[j] > high[i]) break;
         j++;
     }
     res += j - i;
}



感覺很正解阿

這是我們遇到的第一個TLE


這是第一個TLE

往後還會有千千萬萬個TLE



WHY?

N = 100,000

N^2 = 10,000,000,000


不會很久 大約100秒而已

觀察


相信大家都發現了


比較矮的牛根本不會擋到阿


3 1 2 4 ...後面還有很多牛...

[3 1 2]不可能會擋到4後面的牛

因為4最高 最後面

歸納


所以我們不需要的是....


所以不用的可以______。


之後要把當前的牛_____。


然後_______。


自己想喔揪咪 (或上FB跟大家討論!!)

Stack 與單調性維護


http://hoj.twbbs.org/judge


HOJ 130 乳牛問題

HOJ 34 海報

extra. 最大矩形問題





Queue



操作


push 丟進去

front 讀取

pop 丟掉


只有 top 改 front 不一樣

Queue維護順序





模擬神器



沒有題目



Linked-List

What's Linked-List?


想像一個陣列

Like Array


我們不紀錄第 x 號元素

We don't  know who is list[x]


但我們可以知道 x 的下一個跟前一個

but we know Next(x) & Prev(x)

Head



我們額外開一個Head紀錄誰是第一個


one = Next(Head)

two = Next(one)

three = Next(two)

four = Next(three)

...

Tail = Next(最後一個)

So?



一個元素可以被存取要保證

...

Next(A) = B

Prev(B) = A

So?




Insert X between A & B


Prev(B) = x

Next(x) = B


Prev(x) = A;

Next(A) = x;


O(1)

Insert in Array



For(int i=x;i<=N;i++)

array[i+1] = array[i]

array[x] = ITEM


O(lg N)

Remove in Linked-List


p = prev(x)

n = next(x)


next(p) = n

prev(n) = p


O(1)

Find in Linked-list



    x = next(head);

    while(x != tail){

     if (x == something) something;

      x = next(x);

    }


精美的O(N)


x-th in Linked-List


a = head;

for(int i=1;i<=x;)

a = Next(a)



O(N)



you will understand

when you need it.


Go Next!!

Let's Coding!!!



Heap


Heap支援




動態最優先元素




Heap  <-- some ITEMs

Heap --> Max_ITEM





更新O(log N)




插入 push

取最大值 top

丟掉最大值 pop




How does Heap work?





二元樹 Binary Tree

1

[02      03]

[04  05]    [06  07]

[08, 09] [10,11] [12,13] [14,15]


觀察這個圖形(?)(好啦當他是個圖)

...

1對應到2、3

2對應到4、5

3對應到6、7

n對應到...2n跟2n+1




我們定義

2n是n的左小孩(左葉)

2n+1是n的右小孩(右葉)


int left_child (int x){return x*2;}

int right_child (int x){return x*2+1}

int fa(int x){return x/2;}




通常會簡寫成


#define fa(x) x/2

#define lc(x) x*2

#define rc(x) x*2+1




維護根 root

是最優先的元素





維護老爸永遠比小孩優先


Push(x)


把元素放到最底層

不斷跟老爸比較

如果老爸 < 元素

Swap(老爸, 元素)

直到老爸 > 元素

PUSHEEN!

Push (70)



100

[78      54]

[42  67]   [36  43]

[28, 31] [10,12] [03, X ] [ X , X ]

70 in


100

[78      54]

[42  67]   [36  43]

[28, 31] [10,12] [03, 70 ] [ X , X ]

Compare(70, 36)


100

[78      54]

[42  67]   [36  43]

[28, 31] [10,12] [03, 70 ] [ X , X ]

Swap(70, 36)


100

[78      54]

[42  67]   [70  43]

[28, 31] [10,12] [03, 36 ] [ X , X ]


Compare (70, 54)


100

[78      54]

[42  67]   [70  43]

[28, 31] [10,12] [03, 36 ] [ X , X ]

Compare (70, 100)


100

[78      70]

[42  67]   [54  43]

[28, 31] [10,12] [03, 36 ] [ X , X ]

Done


100

[78      70]

[42  67]   [54  43]

[28, 31] [10,12] [03, 36 ] [ X , X ]

POP


100

[78      70]

[42  67]   [54  43]

[28, 31] [10,12] [03, 36 ] [ X , X ]


丟掉100

維護


X

[78      70]

[42  67]   [54  43]

[28, 31] [10,12] [03, 36 ] [ X , X ]


讓下面的遞補上去


(黃色是贏的,橘色是輸的)

BUT


78

[67      70]

[42  12]   [54  43]

[28, 31] [10, X ] [03, 36 ] [ X , X ]


最後會 「缺」 哪一格不確定

下次Push會很麻煩

Back一下



100

[78      70]

[42  67]   [54  43]

[28, 31] [10,12] [03, 36 ] [ X , X ]


我們希望空在 36 這格上

SO...把36拉上來



36

[78      70]

[42  67]   [54  43]

[28, 31] [10,12] [03, X ] [ X , X ]


先把最後一個元素丟上來

再丟下去



36

[78      70]

[42  67]   [54  43]

[28, 31] [10,12] [03, 36 ] [ X , X ]


78

[36      70]

[42  67]   [54  43]

[28, 31] [10,12] [03, 36 ] [ X , X ]

Done



78

[67      70]

[42  36]   [54  43]

[28, 31] [10,12] [03, 36 ] [ X , X ]




Done.

Let's Coding!





補充

Linked-list

實做



標準型

struct  link{
int value;
link*  next, prev;
}

用兩個 指標 指向前後的元素




但是我不會寫指標

小時候 學長跟我說指標很危險




如果元素只出現一次

又剛好是個數字

數字還剛好很小



我告訴你

陣列可以解決一切

你最近會遇到的問題




開個陣列吧

int Next[1000000];
int Prev[1000000];

where is value?
Next[value];
Prev[value];




沒有這麼好的測資?

可是HOJ有  假設有嘛




查詢O(N)...?


因為不知道在哪裡
所以要整個掃過一遍



Where is value x?


看相對位置
Next(x)
Prev(x)




Else?

Insert & Delete






如果數字很大 or 不是數字?




編號!




map<原資料的type,  int>

map[原資料] = int

假設編了1~N號




新增一個N+1號?

map[Date] = N+1


殘忍的複雜度


陣列 + Value 完美的O(1)
無懈可擊


陣列 + Map編號
做一次map -> log(N)
只要跟原資料有關都是logN





什麼時候不能用編號做?

當資料重複時

Data Structure 1

By rilak1328

Data Structure 1

  • 964