資料結構
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
QUEUE
ITEM --> QUEUE
QUEUE --> ITEM
從左邊丟進去 從另一邊拿出來
也可以說是
先進先出 = 排隊
Queue
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 乳牛問題
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
維護根 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
實做
但是我不會寫指標
小時候 學長跟我說指標很危險
如果元素只出現一次
又剛好是個數字
數字還剛好很小
我告訴你
陣列可以解決一切
開個陣列吧
沒有這麼好的測資?
可是HOJ有 假設有嘛
查詢O(N)...?
Where is value x?
看相對位置
Next(x)
Prev(x)
Else?
如果數字很大 or 不是數字?
編號!
map<原資料的type, int>
假設編了1~N號
新增一個N+1號?
殘忍的複雜度
什麼時候不能用編號做?
當資料重複時
Data Structure 1
By rilak1328
Data Structure 1
- 964