C++: リンク リスト - 理論的基礎

C++: リンク リスト - 理論的基礎

リンク リストの理論的基礎:
シングル リンク リスト、ダブル リンク リスト、循環リンク リスト、リンク リストの保存方法、リンク リストの定義とその初期化、リンク リストのノードの削除、ノードの追加操作、リンク リストと配列のパフォーマンスの
違い



リンクリストタイプ

リンク リストはポインタで接続された線形構造であり、各ノードはデータ フィールドとポインタ フィールド (次のノードへのポインタを格納する) の 2 つの部分で構成され、最後のノードのポインタ フィールドがポイントします。 null (null ポインタの意味) にします。

連結リストのエントリノードを連結リストの先頭ノード、つまりheadと呼びます。

単一リスト

単一リスト

二重リンクリスト

単一リンクリストのポインタフィールドは、ノードの次のノードのみを指すことができます。

二重リンク リスト: 各ノードには 2 つのポインター フィールドがあり、1 つは次のノードを指し、もう 1 つは前のノードを指します。

二重リンクリストは、前方および後方の両方でクエリを実行できます。

二重リンクリスト

循環リンクリスト

循環リンク リストは、その名前が示すように、端から端まで接続されたリンク リストです。

循環リンク リストを使用すると、ジョセフ リング問題を解決できます。
循環リンクリスト

リンクリストの保存方法

配列はメモリ内に連続的に分散されますが、リンクされたリストはメモリ内に連続的に分散されません。

リンクリストは、ポインタフィールドのポインタを介してメモリ内の各ノードをリンクするものである。

したがって、リンク リスト内のノードはメモリ上で連続的に分散されるのではなく、メモリ内の特定のアドレスに分散され、割り当てメカニズムはオペレーティング システムのメモリ管理に依存します。

つまり、リンクされたリストは配列よりもメモリ使用率が高くなります。

リンクリストの保存方法


リンクリストの定義と初期化

一般的に使用されるコンストラクター、コンストラクター オーバーロード、およびコンストラクター初期化リストは、定義に使用されます。

//链表的节点
class ListNode
{
    
    
public:
    int val;                                //存储的元素
    ListNode *next;                         //指向下一个节点的指针
    ListNode() : val(0), next(NULL) {
    
    }      //构造函数重载
    ListNode(int x) : val(x), next(NULL) {
    
    } //节点的构造函数,构造函数的初始化列表写法
    ListNode(int x, ListNode *l_next) : val(x), next(l_next) {
    
    }
};

リンク リストの初期化、リンク リストへの一般的に使用されるベクトル

//创建链表
//将vector转成链表
ListNode *createList(vector<int> &nums)
{
    
    
    ListNode *head = new ListNode(nums[0]); //初始化头结点
    ListNode *p = head;                     //赋值给p进行链表创建操作,防止改变head值
    for (int i = 1; i < nums.size(); i++)
    {
    
    
        p->next = new ListNode(nums[i]); //最开始p是head,p指针指向ListNode(nums[1])
        p = p->next;
    }
    return head; //创建完毕返回链表头结点
}

この部分には C++ でパッケージ化されたリンク リストがあり、直接使用できますが、面接ではテストが頻繁に行われるため、手書きできる程度まで習得する必要があります。


リンクリスト操作

ノードの削除

図に示すように、D ノードを削除します。
ノードの削除

C ノードの次のポインタを E ノードに向けるだけです。

ポインタを変更しても、D ノードはメモリに保存されたままではありませんか? このリンクリストには載っていないだけです。

このような場合があるため、C++ では、D ノードを手動で解放し、このメモリを解放することが最善です。

Java や Python などの他の言語には独自のメモリ回復メカニズムがあるため、手動で解放する必要はありません。

実際のノード削除操作では、仮想ヘッドノードを確立し、対象ノードの前のノード上で操作を行うことで構築されることが多いです。

ノードを追加

ノードを追加
リンク リストの追加と削除は両方とも O(1) 操作であり、他のノードには影響を与えないことがわかります。

ただし、5番目のノードを削除する場合、先頭ノードからネクストポインタを経由して削除する4番目のノードまで探索する必要があり、その探索時間はO(n)となる

配列とリンクリストの性能比較

連結リストの特徴と配列の特徴の比較 配列
配列とリンクリストの性能比較
を定義すると基本的に長さは固定されますが、配列の長さを変更したい場合は新たに配列を再定義する必要があります。
したがって、配列はデータ量が固定されており、追加や削除はほとんどないが、クエリが頻繁に行われるシナリオに適しています。

リンク リストの長さは固定されておらず、動的に増減できるため、リンク リストは、データ量が固定されておらず、追加と削除が頻繁に行われるがクエリが少ないシナリオに適しています。


要約する

基本概念をマスターし、初期化と基本操作を定義します。
仮想ヘッド ノードの方法を使用して関連する操作を実行する、ノードの削除の習熟に重点を置きます。
配列とリンク リストのパフォーマンス分析をマスターします。配列は変更が少なくクエリが多いシナリオに適しており、リンク リストは変更が少ないシナリオに適しています。変更が発生し、クエリが減少します。

この記事の参照コードに関するランダムな考え

おすすめ

転載: blog.csdn.net/Bellwen/article/details/128402212