[iOS CS Studio]優先キュー
6229 ワード
21.06.26
これは学習内容を整理するための文章で、完全に正確ではないかもしれません.
参考までに、内容が足りないと思ったら、他の文章を読むこともできます.
+間違った部分、修正が必要な部分は、いつでもフィードバックしてください.😊
by. ryalya
入る前に.
前回の記事では、スタックとキューからQについて簡単に理解しました.
簡単に再定義すると、Queueは以下のようになります.
最初の入力/出力=入力/出力
入れ順に出る(先進的なデータ先進)
リンクリストのインプリメンテーション.
-典型的な例は、銀行ウィンドウキューです.
-入り口と出口が分かれていると思えば簡単です.
前述したようにQueueはFIFO形式の資料構造である.
ただし、優先順位キュー(Priority Queue、優先順位キュー)は、入る順番に関係なく優先順位の高いデータが先に表示されます.
データ構造スタックでは、heapは優先キューのために作成されたデータ構造である.
これは、優先キューがheapというデータ構造によって実現できるためである.
しかし,優先キューを配列やリンクリストで実現できる以上,なぜhipで実現するのか.
ChanBLOGで見た内容は地理的によく理解され、そのまま持ってきた.😊
配列の先頭から優先度の高い順に入れると、先頭のインデックスを直接使用すればよいので、優先度の高いデータを返すのは難しくありません.
しかし,優先順位が中間の挿入過程では,後続のデータまでインデックスを1つ後ろに押すという欠点がある.
最悪の場合、すべてのインデックスを参照して、挿入する場所を検索する必要があります.
すなわち,データがnの場合,時間的複雑度はO(n)である.
→アレイ別実施時の時間的複雑度:削除はO(1)、挿入はO(n)
優先度の高い順序で接続すると、優先度の高いデータを返すのは配列と同じように簡単です.
ただし、接続リストの挿入プロセスは配列と同様に、その位置を見つける必要があります.
最悪の場合、行き止まりになります.
→接続リストを実施する際の時間的複雑度:削除はO(1)、挿入はO(n)
hipの場合、削除または挿入中に親と子の比較のみが行われます.
バイナリツリーの高さを1つ増加するごとに、格納可能なデータは2倍に増加し、比較演算回数は1回増加します.
すなわち,削除や挿入が最悪であれば,O(log 2 n)の時間的複雑さがある.
→接続リストで実現する場合の時間的複雑度:O(log 2 n)に削除し、O(log 2 n)に挿入する
このように、配列や接続リストが削除時に時間的複雑度の優位を占めていても、挿入する時間的複雑度はお尻に基づいているので、ずれの大きい配列や接続リストよりもお尻を使って実現!!
データ構造優先キューとhipによる時間的複雑さをまとめた表です.
Priority Queueの演算はheapを利用しているのでheapと同じと考えられる.
新しいノードを追加するときは,最末端から追加し,自分の親のインデックス(index-1)/2と比較し,逆に上昇し,hip条件に合致するか否かを比較し,条件に合致するまで親と子の位置を置き換える.
上(ルート)ノードも削除し、最後のノードをルートとして挿入し、ヒップ条件を下に比較し、親ノードと子ノードの位置を条件に一致するまで置き換えます.
SWIFTを使用して優先キューを実装するコードは、次のとおりです.
優先キュー優先キューから持ってきました.
しかしSweetでは配列で表現する方が効率的ですか?私はこのような話を見ましたが、これはどういう意味ですか?
配列/リンクリストを使用して優先キューを実装しない理由:ChanBLOG
時間複雑度テーブル:データ構造優先キューとhip
Priority Queue実施:優先キュー優先キュー
これは学習内容を整理するための文章で、完全に正確ではないかもしれません.
参考までに、内容が足りないと思ったら、他の文章を読むこともできます.
+間違った部分、修正が必要な部分は、いつでもフィードバックしてください.😊
by. ryalya
入る前に.
前回の記事では、スタックとキューからQについて簡単に理解しました.
簡単に再定義すると、Queueは以下のようになります.
最初の入力/出力=入力/出力
入れ順に出る(先進的なデータ先進)
リンクリストのインプリメンテーション.
-典型的な例は、銀行ウィンドウキューです.
-入り口と出口が分かれていると思えば簡単です.
Priority Queueとは?
前述したようにQueueはFIFO形式の資料構造である.
ただし、優先順位キュー(Priority Queue、優先順位キュー)は、入る順番に関係なく優先順位の高いデータが先に表示されます.
一般的なQueueは、次のような線形構造を有する。
ただし、Priority Queueの構造は以下のようにツリー構造と見なすべきである。
データ構造スタックでは、heapは優先キューのために作成されたデータ構造である.
これは、優先キューがheapというデータ構造によって実現できるためである.
しかし,優先キューを配列やリンクリストで実現できる以上,なぜhipで実現するのか.
ChanBLOGで見た内容は地理的によく理解され、そのまま持ってきた.😊
配列/リンクリストを使用して優先キューを実装しないのはなぜですか?
整列
配列の先頭から優先度の高い順に入れると、先頭のインデックスを直接使用すればよいので、優先度の高いデータを返すのは難しくありません.
しかし,優先順位が中間の挿入過程では,後続のデータまでインデックスを1つ後ろに押すという欠点がある.
最悪の場合、すべてのインデックスを参照して、挿入する場所を検索する必要があります.
すなわち,データがnの場合,時間的複雑度はO(n)である.
→アレイ別実施時の時間的複雑度:削除はO(1)、挿入はO(n)
リンクリスト
優先度の高い順序で接続すると、優先度の高いデータを返すのは配列と同じように簡単です.
ただし、接続リストの挿入プロセスは配列と同様に、その位置を見つける必要があります.
最悪の場合、行き止まりになります.
→接続リストを実施する際の時間的複雑度:削除はO(1)、挿入はO(n)
¥¥¥
hipの場合、削除または挿入中に親と子の比較のみが行われます.
バイナリツリーの高さを1つ増加するごとに、格納可能なデータは2倍に増加し、比較演算回数は1回増加します.
すなわち,削除や挿入が最悪であれば,O(log 2 n)の時間的複雑さがある.
→接続リストで実現する場合の時間的複雑度:O(log 2 n)に削除し、O(log 2 n)に挿入する
このように、配列や接続リストが削除時に時間的複雑度の優位を占めていても、挿入する時間的複雑度はお尻に基づいているので、ずれの大きい配列や接続リストよりもお尻を使って実現!!
データ構造優先キューとhipによる時間的複雑さをまとめた表です.
優先順位キューの実装
Priority Queueの演算はheapを利用しているのでheapと同じと考えられる.
新しいノードを追加するときは,最末端から追加し,自分の親のインデックス(index-1)/2と比較し,逆に上昇し,hip条件に合致するか否かを比較し,条件に合致するまで親と子の位置を置き換える.
上(ルート)ノードも削除し、最後のノードをルートとして挿入し、ヒップ条件を下に比較し、親ノードと子ノードの位置を条件に一致するまで置き換えます.
SWIFTを使用して優先キューを実装するコードは、次のとおりです.
優先キュー優先キューから持ってきました.
Heap実施
struct Heap<T: Comparable> {
var nodes: [T] = []
let sort: (T,T) -> Bool
init(sort: @escaping (T,T) -> Bool) {
self.sort = sort
}
insert (push)
// Heap에 데이터 추가 (push)
mutating func insert(_ element: T) {
let count = nodes.count
nodes.append(element)
up(count - 1)
}
delete (pop)
// Heap에서 데이터 꺼내면서 삭제 (pop)
mutating func delete() -> T? {
if nodes.isEmpty {
return nil
}
if nodes.count == 1 {
return nodes.removeFirst()
}
nodes.swapAt(0, nodes.count - 1)
let result = nodes.removeLast()
down(0)
return result
}
// Heap에서 특정 데이터 삭제
mutating func remove(_ element: T) {
if let index = nodes.firstIndex(of: element) {
nodes.swapAt(index, nodes.count - 1)
nodes.removeLast()
up(index)
down(index)
}
}
// Heap에서 데이터 전체 삭제
mutating func removeAll(_ element: T) {
var count = nodes.count
remove(element)
while nodes.count < count {
remove(element)
count = nodes.count
}
}
// Heap에서 첫 데이터 pop
func peek() -> T? {
return nodes.first
}
データのソート
// Heap 데이터 아래방향으로 비교 정렬
mutating func down(_ index: Int) {
var index = index
let count = nodes.count
while 2 * index + 1 < count {
var i = 2 * index + 1
if i < (count - 1) && sort(nodes[i], nodes[i + 1]) {
i += 1
}
if !sort(nodes[index], nodes[i]) {
break
}
nodes.swapAt(index, i)
index = i
}
}
// Heap 데이터 윗방향으로 비교 정렬
mutating func up(_ index: Int) {
var index = index
while index > 0 && !sort(nodes[(index - 1)], nodes[index]) {
nodes.swapAt((index - 1) / 2, index)
index = (index - 1) / 2
}
}
}
結果値
var queue: Heap<Int> = Heap<Int>() {
return $0 > $1
}
queue.insert(3)
queue.insert(5)
queue.insert(2)
queue.insert(1)
queue.insert(6)
queue.insert(7)
queue.insert(4)
// nodes: [7, 5, 6, 1, 3, 2, 4] -- 결과값
サンプルコードによる実装は難しくないことを理解した.しかしSweetでは配列で表現する方が効率的ですか?私はこのような話を見ましたが、これはどういう意味ですか?
Reference
配列/リンクリストを使用して優先キューを実装しない理由:ChanBLOG
時間複雑度テーブル:データ構造優先キューとhip
Priority Queue実施:優先キュー優先キュー
Reference
この問題について([iOS CS Studio]優先キュー), 我々は、より多くの情報をここで見つけました https://velog.io/@ryalya/iOS-CS-Study-우선순위-큐Priority-Queueテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol