すべてのプログラマーが知っておくべき 8 つのデータ構造
データ構造は、保存されたデータに対する操作をより効率的に実行できるようにする、データを整理および保存するための特別な方法です。データ構造は、コンピュータ サイエンスやソフトウェア エンジニアリングにおいて幅広く多様に使用されています。
開発されたほぼすべてのプログラムまたはソフトウェア システムはデータ構造を使用します。さらに、データ構造はコンピューター サイエンスとソフトウェア エンジニアリングの基礎です。これは、ソフトウェア エンジニアリングの面接の質問に関して重要なトピックです。したがって、開発者はデータ構造をよく理解する必要があります。
この記事では、すべてのプログラマーが知っておくべき 8 つの一般的なデータ構造について簡単に説明します。
1.アレイ
配列は、同じデータ型の項目を保持できる固定サイズの構造です。整数の配列、浮動小数点の配列、文字列の配列、さらには配列の配列 (2D 配列など) にすることもできます。配列にはインデックスが付けられます。つまり、ランダム アクセスが可能です。
図 1. 配列の基本用語の視覚化
配列操作
· トラバーサル: すべての要素をトラバースして出力します。
· 挿入: 1 つ以上の要素を配列に挿入します。
· 削除: 配列から要素を削除します。
· 検索: 配列内の要素を検索します。値またはインデックスで要素を検索できます
更新: 指定されたインデックスにある既存の要素の値を更新します。
配列の用途
· 配列リスト、ヒープ、ハッシュ テーブル、ベクトル、行列などの他のデータ構造を構築するための基礎として使用されます。
· 挿入ソート、クイック ソート、バブル ソート、マージ ソートなどのさまざまなソート アルゴリズムに使用されます。
2. リンクリスト
リンク リストは、相互にリンクされた項目の線形シーケンスで構成される順序構造です。したがって、データには順次アクセスする必要があり、ランダムアクセスは不可能です。リンク リストは、動的セットのシンプルかつ柔軟な表現を提供します。
リンクされたリストに関する次の用語を考えてみましょう。図 2 を参照すると、明確なアイデアが得られます。
· リンク リスト内の要素はノードと呼ばれます。
· 各ノードには、キーとその後続ノード (next と呼ばれる) へのポインタが含まれています。
· head という名前の属性は、リンクされたリストの最初の要素を指します。
· リンクされたリストの最後の要素は末尾と呼ばれます。
図 2. リンク リストの基本用語の視覚化
以下に、利用可能なさまざまなタイプのリンク リストを示します。
· 単一リンク リスト - 項目は前方向にのみ移動できます。
· 二重リンク リスト - 項目は前方および後方方向に移動できます。ノードは、前のノードを指す、previous と呼ばれる追加のポインターで構成されます。
· 循環リンク リスト - 先頭にある前のポインタが末尾を指し、末尾にある次のポインタが先頭を指すリンク リスト。
リンク リスト操作
· 検索: 単純な線形検索を通じて、指定されたリンク リスト内でキー k を持つ最初の要素を検索し、要素へのポインタを返します。
· 挿入: リンクされたリストにキーを挿入します。挿入には、リストの先頭に挿入、リストの最後に挿入、リストの途中に挿入の 3 つの異なる方法があります。
· 削除: 指定されたリンク リストから要素 x を削除します。ノードを 1 回の手順で削除することはできません。削除はリストの先頭から削除、リストの最後から削除、リストの途中から削除の3通りの方法があります。
リンク リストの応用
· コンパイラ設計におけるシンボル テーブル管理に使用されます。
· Alt Tab を使用してプログラムを切り替えるために使用されます (循環リンク リストを使用して実装)。
3.スタック
スタックは、多くのプログラミング言語で一般的に見られる LIFO (後入れ先出し - 最後に配置された要素に最初にアクセスできる) 構造です。この構造は、現実世界のスタック (ボードの積み重ね) に似ているため、「スタック」と呼ばれます。
画像出典: pixabay
スタック操作
以下に、スタック上で実行できる 2 つの基本的な操作を示します。スタック操作をより深く理解するには、図 3 を参照してください。
· Push Push: 要素をスタックの先頭に挿入します。
· Pop: 先頭の要素を削除して返します。
図 3. スタックの基本動作の視覚化
さらに、スタックのステータスを確認するために、次の追加関数が提供されます。
· Peep: スタックの最上位要素を削除せずに返します。
· isEmpty: スタックが空かどうかを確認します。
· isFull: スタックがいっぱいかどうかを確認します。
スタックのアプリケーション
· 式の評価用 (例: 数式を解析して評価するための操車場アルゴリズム)。
· 再帰的プログラミングで関数呼び出しを実装するために使用されます。
4.キュー
キューは、多くのプログラミング言語で一般的に見られる FIFO (先入れ先出し - 最初に配置された要素に最初にアクセスできる) 構造です。この構造は、現実世界の行列 (人々が列に並んで待つ) に似ているため、「キュー」と呼ばれます。
画像ソース: pixabay
キュー操作
以下に、キューに対して実行できる 2 つの基本的な操作を示します。スタック操作をより深く理解するには、図 4 を参照してください。
· エンキュー: 要素をキューの最後に挿入します。
· デキュー: キューの先頭から要素を削除します。
図 4. キューの基本操作の視覚化
キュー アプリケーション
· マルチスレッドでのスレッドの管理に使用されます。
· キューイング システム (優先キューなど) を実装するため。
5. ハッシュテーブル
ハッシュ テーブルは、各キーに関連付けられたキーを持つ値を格納するために使用されるデータ構造です。さらに、値に関連付けられたキーがわかっている場合は、ルックアップを効果的にサポートします。したがって、データ サイズに関係なく、挿入と検索は非常に効率的です。
テーブルに格納する場合、直接アドレス指定では値とキーの間の 1 対 1 マッピングが使用されます。ただし、キーと値のペアが多数ある場合、このアプローチには問題があります。テーブルには多くのレコードが含まれ、非常に大きくなり、一般的なコンピューターで使用可能なメモリを考慮すると、保存するのが非現実的か、不可能になる可能性があります。この問題を回避するために、ハッシュ テーブルを使用します。
ハッシュ関数
ハッシュ関数 (h) と呼ばれる特別な関数は、直接アドレス指定における上記の問題を解決するために使用されます。
直接アクセスでは、キー k を持つ値がスロット k に格納されます。ハッシュ関数を使用すると、各値が指すテーブル (スロット) のインデックスを計算できます。特定のキーに対してハッシュ関数を使用して計算された値はハッシュ値と呼ばれ、値がマップされるテーブルのインデックスを表します。
・h:ハッシュ関数
・k:ハッシュ値を求めるキー
・m:ハッシュテーブルのサイズ(利用可能なスロット数)。m には、正確な 2 のべき乗に近くない素数が適しています。
図 5. ハッシュ関数の表現
・1→1→1
・5→5→5
・23→23→3
・63→63→3
上記の最後の 2 つの例から、ハッシュ関数が複数のキーに対して同じインデックスを生成するときに衝突が発生することがわかります。適切なハッシュ関数 h を選択し、連鎖やオープン アドレス指定などの手法を使用することで、衝突を解決できます。
ハッシュ テーブルのアプリケーション
· データベースのインデックスを実装するために使用されます。
· 連想配列の実装に使用されます。
· 「設定」データ構造を実装するために使用されます。
6.ツリー
ツリーは、データが階層的に編成され、相互にリンクされている階層構造です。この構造は、項目が線形順序でリンクされているリンク リストとは異なります。
過去数十年にわたり、特定の用途に適し、特定の制約を満たすために、さまざまな種類の樹木が開発されてきました。例としては、二分探索ツリー、B ツリー、赤黒ツリー、拡張ツリー、AVL ツリー、n 分ツリーなどがあります。
二分探索ツリー
名前が示すように、二分探索ツリー (BST) は、データが階層構造で編成された二分木です。このデータ構造は、値をソートされた順序で保存します。これについては、このコースで詳しく説明します。
二分探索ツリーの各ノードには次のプロパティが含まれます。
· key: ノードに格納されている値。
· left: 左の子へのポインタ。
· 右: 正しい子へのポインタ。
・p:親ノードへのポインタ。
二分探索ツリーには、他のツリーとは異なる固有の特性があります。このプロパティは、binary-search-tree プロパティと呼ばれます。
x を二分探索木のノードとする。
· y が x の左サブツリーのノードの場合、y.key ≤ x.key
· y が x の右側のサブツリー内のノードの場合、y.key ≥ x.key
図 6. ツリーの基本用語の視覚化。
ツリーのアプリケーション
· バイナリ ツリー: 式パーサーと式ソルバーを実装するために使用されます。
· 二分探索ツリー: データを継続的に入出力する多くの検索アプリケーションで使用されます。
· ヒープ: Java オブジェクトを保存するために JVM (Java 仮想マシン) によって使用されます。
· トラップ: ワイヤレス ネットワーク用。
7.ヒープ
ヒープは、親ノードの値がその子ノードと比較され、それに応じて配置されるバイナリ ツリーの特殊なケースです。
ヒープを表現する方法を見てみましょう。ヒープはツリーと配列を使用して表現できます。図 7 と図 8 は、バイナリ ツリーと配列を使用してバイナリ ヒープを表す方法を示しています。
図 7. ヒープのバイナリ ツリー表現
図 8. ヒープの配列表現
ヒープには 2 つのタイプがあります。
· 最小ヒープ - 親のキーは子のキー以下です。これは min-heap 属性と呼ばれます。ルートにはヒープの最小値が含まれます。
· 最大ヒープ サイズ - 親のキーは子のキー以上です。これは max-heap 属性と呼ばれます。ルートにはヒープの最大サイズが含まれます。
ヒープの用途
· ヒープのプロパティに基づいて優先度の値を並べ替えることができるため、優先度キューの実装に使用されます。
· キュー機能は、ヒープを使用して O(log n) 時間で実装できます。
· 指定された配列内の k 個の最小 (または最大) 値を見つけるために使用されます。
· ヒープソートアルゴリズムで使用されます。
8. 図
グラフは、有限の頂点またはノードのセットと、これらの頂点を接続するエッジのセットで構成されます。
グラフの次数は、グラフ内の頂点の数です。グラフのサイズは、グラフ内のエッジの数です。
2 つのノードが同じエッジで接続されている場合、それらは隣接ノードと呼ばれます。
有向グラフ
グラフ G は、そのすべてのエッジが開始頂点と終了頂点を示す方向を持っている場合、有向グラフと呼ばれます。
(u, v) が頂点 u に入射するか、頂点 u から出てから、頂点 v に入射するか、頂点 v に入ると言います。
自己ループ: 頂点からそれ自身までのエッジ。
無向グラフ
グラフ G のすべての辺に方向がない場合、それは無向グラフと呼ばれます。2 つの方法で 2 つの頂点間を伝播できます。
頂点がグラフ内の他のノードに接続されていない場合、その頂点は孤立していると言われます。
図 9. グラフの用語の視覚化
グラフの用途
· ソーシャル メディア ネットワークを表すために使用されます。各ユーザーは頂点であり、ユーザーが接続されるとエッジが作成されます。
· 検索エンジンを表すために使用される Web ページとリンク。インターネット上の Web ページは、ハイパーリンクを通じて相互にリンクされています。各ページは頂点であり、2 つのページ間のハイパーリンクはエッジです。Googleのページランキングに使用されます。
· GPS で位置とルートを表すために使用されます。位置が頂点、位置を結ぶ経路がエッジとなります。2 つの場所間の最短パスを計算するために使用されます。