私の世界へようこそ
コレクション列:リンクされたリスト
著者の記事があなたのお役に立てば幸いです。不備があれば修正してください。一緒に学び、コミュニケーションをとりましょう。
序文
- ここに書いているのは、リンクリストの罠に陥ったことについての質問です。私が罠にはまるまでの過程を詳しく書きました。皆さんも罠にはまったことがあると思います。このコラムは今後も更新していきます。 ご協力ありがとうございます。
————————過程に全力を注ぎ、結果には無頓着である
質問 1: リンクされたリストの最後から n 番目のノードを削除します。
住所:ojタイトルアドレス
問題解決のアイデア:
- 1. 暴力的なトラバーサル:
最初に 1 回トラバースしてリンク リストにノードがいくつあるかを見つけます (最初のトラバーサル)。次に 2 回目のトラバースで最後から n 番目のノードを見つけて削除し、元のアドレスに戻ります。この方法は、この質問に対して比較的簡単な実装方法であると言えます。ここで別の方法について話したいと思います。
2. 3 ポインタ方式:
まず、tail ポインタ、sur ポインタ、および dst ポインタの 3 つのポインタを作成します。sur ポインタと dst ポインタは、最初はリンク リストの開始アドレスを指し、テール ポインタはその前のバイトのアドレスを指します。 sur ポインタ これは、
次の最初の物理図で sur のアドレスが見つかるスペースを再度開く必要があります。
注: リンク リストのアドレスは接続されていないため、アドレスはランダムであるとみなすことができます。写真内のアドレスは、便宜と観察を容易にするために、すべて私がランダムにまとめたものです。アイデア: まず、dst ポインタを n ノード後方に移動させて、dst ポインタと sur ポインタが n ノード離れるようにします。次に、dst ポインタが null ポインタを指すまで、これら 3 つのポインタを一度に 1 ノードずつ後方に移動させます。その場合、 sur は下から n 番目のノードを指します (このステップの概念は非常に重要であり、明確に考える必要があります)このとき、削除されるノードのアドレスがあり、また、削除されるノードのアドレスもあります。末尾ポインタが指すノードの上のノードを削除すると、削除は非常にうまく完了できます。
上記はアイデアです。以下でそれを実装してみましょう。最後に物理図:
struct ListNode* removeNthFromEnd(struct ListNode* head, int n ) {
// write code here
//sur指针是指向要删除的那个节点,dst是与sur保持间距n的,tail是sur前一个节点
struct ListNode* sur = head, *dst = head;
struct ListNode*tail =(struct ListNode*)malloc(sizeof(struct ListNode));
tail->next=sur;
//先让dst指针走n个节点
while (n--) {
dst = dst->next;
}
while (dst) {
//三个指针一起出发,tail指针始终指向sur指针前前一个节点
dst = dst->next;
sur = sur->next;
tail = tail->next;
}
//删除
if (head == sur) {
//如果sur没动说明要删的就在第一个
head = head->next;
sur = head->next;
} else {
//要删的只要找到sur指针的前一个节点,就可以让sur后一个节点与之相连
tail->next = sur->next;
}
return head;
}
質問 2: リンク リストの中間ノード
住所:ojアドレス
問題解決のアイデア:
- 1. 暴力的な走査方法:
この質問の通常の考え方によれば、まずリンク リスト内のすべてのノードの数を走査し、次に中間点を取得し、最後にその点を指すアドレスを返す必要があります。この方法は次のとおりです。非常に一般的なので、ここでは詳しく説明しませんが、次の方法について詳しく説明したいと思います。- 2.高速ポインタ方式と低速ポインタ方式:
このメソッドのアイデアは次のとおりです: まず、2 つのポインターを設定します: それぞれ高速ポインターと低速ポインターです。まず、両方のポインターはリンクされたリストの開始位置を指し、低速で次のノードに移動し、高速で移動します。次の 2 つのノードに移動します。高速ポインタが停止するまで、高速ポインタはいつ停止しますか?さまざまな状況があるはずです。リンクされたリストのノードが偶数の場合、高速は空になるまで移動します。リンクリストのサマリーポイントが奇数の場合、高速に終了点で停止します。
----奇数の場合: ロジック図:
第 1 ステップ:
第 2 ステップ:
第 3 ステップ
偶数の場合:
ロジック図:
第 1 ステップ:
第 2 ステップ:
第 3 ステップ:
第 4 ステップ:
コード:
struct ListNode* middleNode(struct ListNode* head ) {
// write code here
//设置快慢指针
struct ListNode*sur=head,*dst=head;
//当dst指针为空或dst指向的next为空就停下
while(dst && dst->next)
{
sur=sur->next;
dst=dst->next->next;
}
return sur;
}
質問 3: 2 つの並べ替えられたリンク リストを結合します。
住所:ojアドレス
問題解決のアイデア:
まず第一に、リンク リストはシーケンシャル リストとは異なり、機能しないアイデアもあります。しかし、利点もあります。リンク リストは一度に 1 つのノードに接続されており、いつでも解体できます。マージ メソッドを使用すると、次のことができます。まず 2 つのポインタを作成し、
マージする必要がある 2 つのリンク リストのセットを開始位置から比較します。ポインタは小さい方の値の末尾に挿入され、もう 1 つのポインタはマージする必要がある前のノードを検索します。尾部の挿入を容易にするために挿入される。
1<2 を比較し、末尾に 1 を挿入します。最初の挿入の場合、先頭ポインタと末尾ポインタは同時に 1 のアドレスを指す必要があります。最初の挿入でない場合は、Head1 のアドレスを指します。を tail->next に与え、次にテールポインタが tail->next を指すようにし、最後に pHead1 が次のノードを指すようにします。
- 2<3 の場合、最後に 2 のアドレスを挿入します。上記の手順と同じです。
注: これは、このポイントの後の最初の挿入ではありません。末尾ポインタが末尾の次のノードを指すようにすることを忘れないでください。
以下の手順はほぼ同じで、
リンク リストが 1 つなくなるまで、残りのリンク リストの末尾を直接挿入し、最後に先頭のポインタを返し、最後に
先頭のポインタを返します。
しかし、これは正しいでしょうか?
いいえ、もう 1 つの手順を忘れていました。2 つのリンク リストの一方が空の場合、このプログラムの結果は間違いなくエラーを報告するため、最初に判断する必要があります。2 つのリンク リストの一方が空の場合; その後、他のリンクされたリストに直接戻ります。
コード:
struct ListNode* Merge(struct ListNode* pHead1, struct ListNode* pHead2 ) {
// write code here
//如果其中一个链表为空,则直接返回另一个链表
if(pHead1==NULL)
return pHead2;
if(pHead2==NULL)
return pHead1;
struct ListNode* head = NULL, *tail = NULL;
//判断哪个链表先为空,就跳出去
while (pHead1 && pHead2) {
if (pHead1->val < pHead2->val) {
if (tail == NULL) {
//第一次尾插
head = tail = pHead1;
} else {
//不是第一次尾插
tail->next = pHead1;
tail=tail->next;
}
//让篇pHead1指针找到下一个结点
pHead1 = pHead1->next;
} else {
if (tail == NULL) {
//第一次尾插
head = tail = pHead2;
} else {
//不是第一次尾插
tail->next = pHead2;
tail=tail->next;
}
//让篇pHead2指针找到下一个结点
pHead2 = pHead2->next;
}
}
//判断哪个链表先为空,然后让另一个链表直接尾插入;
if(pHead1)
tail->next=pHead1;
if(pHead2)
tail->next=pHead2;
return head;
}
要約する
ここで、見守ってくださった退役軍人の方々に感謝したいと思います。そして、ここで子供たちから、サポートしてくれた皆さんに感謝したいと思います。上記の質問は、子供たちの現在の能力に基づいています。より良い方法がある場合は、話し合いの場で一緒に話し合うことができます。コメントエリア. 将来的には、子供の知識の蓄えが増えるにつれて、子供は間違いなくそれを最適化するでしょう!!
最後に、
これだけは言っておきたいのですが、
----------過程に全力で取り組み、結果には無関心であれ、これは
私が自分に言い聞かせていることでもあります。