10 日間で基本的なデータ構造を学ぶ - 4 日目 (リンク リスト)

ここに画像の説明を挿入します

リンクリストの基本概念

リンク リストは線形データ構造であり、配列とは異なり、リンク リストの要素 (ノード) はポインタを介して相互に接続されます。リンク リストには次の基本概念があります。

  • ノード: リンクされたリスト内の各データ項目はノードと呼ばれ、各ノードにはデータと次のノードへのポインタが含まれます。

  • ヘッド ノード: リンク リストの最初のノードはヘッド ノードと呼ばれ、通常、リンク リスト全体の開始位置を表すために使用されます。

  • 末尾ノード: リンクされたリストの最後のノードは末尾ノードと呼ばれ、そのポインタは通常 null を指します。

単連結リストと二重連結リストの違い

リンク リストは、単一リンク リスト二重リンク リストの2 つの主なタイプに分類できます。

  • 単一リンク リスト: 各ノードには、次のノードへのポインタのみが含まれます。単一リンクリストのメモリオーバーヘッドはわずかですが、簡単に逆にたどることはできません。

  • 二重リンク リスト: 各ノードには、次のノードと前のノードへのポインターが含まれます。二重リンクリストでは双方向のトラバーサルが可能ですが、メモリのオーバーヘッドが大きくなります。

リンクされたリストに対する一般的な操作

リンク リストは、次の一般的な操作をサポートします。

  1. ノードの挿入: リンク リストに新しいノードを挿入するには、通常、隣接するノードのポインタを更新する必要があります。

  2. ノードの削除: リンク リストからノードを削除するには、通常、隣接するノードのポインタを更新する必要があります。

  3. 逆リンク リスト: リンク リスト内のノードの順序を逆にします。

  4. リンク リストの長さを取得する: リンク リスト内のノードの数を取得します。

以下は、単一リンク リストを作成し、ノードを挿入および削除し、リンク リストの長さを取得する簡単な C++ の例です。

#include <iostream>

// 链表节点定义
struct Node {
    
    
    int data;     // 节点数据
    Node* next;   // 指向下一个节点的指针
};

int main() {
    
    
    // 创建链表头节点
    Node* head = nullptr;
    
    // 插入节点
    Node* newNode1 = new Node;
    newNode1->data = 1;
    newNode1->next = nullptr;
    head = newNode1;

    Node* newNode2 = new Node;
    newNode2->data = 2;
    newNode2->next = nullptr;
    newNode1->next = newNode2;

    // 删除节点
    delete newNode1;
    head = newNode2;

    // 获取链表长度
    int length = 0;
    Node* current = head;
    while (current != nullptr) {
    
    
        length++;
        current = current->next;
    }

    std::cout << "链表长度:" << length << std::endl;

    return 0;
}

練習問題:

  1. 単一リンクリストと二重リンクリストの主な違いは何ですか? どのような状況で、単一リンク リストまたは二重リンク リストの使用を選択しますか?
  2. データの保存と管理には配列よりもリンク リストの方が適している状況について説明します。
  3. リンクされたリストに新しいノードを挿入するにはどうすればよいですか? この操作の時間計算量はどれくらいですか?
  4. リンクされたリスト内のノードを削除するにはどうすればよいですか? この操作の時間計算量はどれくらいですか?

単一リンクリストと二重リンクリストの主な違いは何ですか? どのような状況で、単一リンク リストまたは二重リンク リストの使用を選択しますか?

  • 単一リンク リスト: 単一リンク リストの各ノードには、ポインターが 1 つだけ含まれます。通常は、次のノードへのポインターです。この構造はメモリのオーバーヘッドが少なくなりますが、一方向にしかトラバースできません。単一リンク リストは、メモリ オーバーヘッドが制限されている場合にデータへの一方向のアクセスが必要なシナリオに適しています。

  • 二重リンク リスト: 二重リンク リストの各ノードには 2 つのポインターが含まれており、1 つは次のノードを指し、もう 1 つは前のノードを指します。これにより双方向のトラバーサルが可能になりますが、メモリのオーバーヘッドが大きくなります。二重リンク リストは、双方向のトラバーサルや、リンク リストの途中でノードを頻繁に挿入および削除する必要がある状況に適しています。

単一リンク リストを使用するか二重リンク リストを使用するかの選択は、要件によって異なります。一方向のアクセスのみが必要な場合、またはメモリが制限されている場合は、単一リンク リストの方が適切な場合があります。双方向のトラバーサルやノードの頻繁な挿入と削除が必要な場合は、二重リンク リストの方が適切な場合があります。

データの保存と管理には配列よりもリンク リストの方が適している状況について説明します。

次の状況では、配列よりもリンク リストの方が適しています。

  • 動的サイズ: データ セットのサイズが実行時に変化する場合、配列のサイズは通常は固定されているのに対し、リンク リストは動的にメモリを割り当てたり解放したりできるため、より適しています。

  • 頻繁な挿入と削除: データ項目の頻繁な挿入と削除が必要な場合、挿入と削除の操作の時間計算量が O(1) であるのに対し、配列での同じ操作には通常 O が必要となるため、リンク リストの方が配列より効率的です。 (n)。

  • ランダム アクセスは不要: ランダム アクセス (インデックスを使用) せずにデータに順次アクセスする必要があるだけの場合は、リンク リストが適しています。

リンクされたリストに新しいノードを挿入するにはどうすればよいですか? この操作の時間計算量はどれくらいですか?

新しいノードを挿入する手順は次のとおりです。

  • 新しいノードを作成し、そのデータとポインタを設定します。
  • 新しいノードのポインタを更新して、元のリンク リスト内の適切な位置にあるノードを指すようにします。
  • 元のリンク リスト内の隣接ノードのポインタを、新しいノードを指すように更新します。

この操作の時間の複雑さは、挿入位置によって異なります。挿入位置がわかっている場合は、ポインターを変更するだけでよいため、時間計算量はO(1)になります。リンク リストの途中に挿入する必要があり、挿入位置を見つけるためにトラバースする必要がある場合、時間計算量はO(n)になります。ここで、n はリンク リストの長さです。

リンクされたリスト内のノードを削除するにはどうすればよいですか? この操作の時間計算量はどれくらいですか?

リンク リスト内のノードを削除する手順は次のとおりです。

  • 削除するノードを見つけます。
  • 隣接するノードのポインタを更新して、削除するノードをスキップします。
  • 削除するノードのメモリを解放します。

この操作の時間の複雑さは、削除するノードを見つけるのにかかる時間によって異なります。削除位置がわかっている場合は、ポインタを変更するだけでよいため、計算量はO(1)となる。削除するノードを見つけるためにリンク リストを走査する必要がある場合、時間計算量はO(n)になります。ここで、n はリンク リストの長さです。

メモリ リークを避けるために、ノードを削除する前に必ずノードのメモリを解放してください。

おすすめ

転載: blog.csdn.net/m0_53918860/article/details/133554321