- 問題のリストが出現プログラマのインタビューの最高周波数の一つであるフリップ、一般的な解決策は、再帰と反復の2種類に分かれています。レビューがインターネット上の情報を見つけたとき最近、のみ行う方法を告げたが、正しく実装プロセスと二つの方法の原理を導入していませんでした。だから私は適切にブログの記事を整理する必要性を感じて、ステップバイステップでは、実装の詳細を理解するのに役立ちます。
- 私たちは、反復がチェーンの最後までループするまで、前方から後方に順次処理されて知っている、と逆に再帰、チェーンの最後に最初の繰り返しとなっているが、再帰的な標準ベースの判断、層によって層であり、その後のプロセスの最初に戻ります。要約すると、リストの反復の順序を反転させる動作がチェーンからチェーンのヘッドエンドにあり、再帰のための鎖の末端から最初の鎖です。今、私は達成するための詳細を分析するために、詳細なグラフィックを使用します。
1.非再帰(反復)の方法
- 図に示すように、反復方法は、第1のチェーンから処理を開始することである。5ストレージの数のリスト。
- まず、リストは二つのポインタのために提供されています。
- 古いリストが続くそれぞれの新しいリストの後に追加され、図2に示すように、新しいヘッドポインタNewH新しいリストヘッドのリストは、移動されます。それは、ここで注意しなければならない、P>次のポイントに直接NewH上図をすぐに来ることができないので、格納アドレス2にもアクセスできなくなり、追跡データの保存されたリストを破棄されます。しかし、それは一時的に、一時的なポインタTMPを設定したアドレス空間、元のリストのフォローアップのデータの保全に>次の点をP-を指している必要があります。そして、P->次のポイントNewHを聞かせて、最終的にP = tmpが元のリストにデータを取り出すことができ、すべてのアクセス・サイクルは、それを拡大し続けることができます。
- ポインタがNULLにPポインタを反復停止するまで後方に移動し続けます。
- 最後のステップ:
- 非再帰プログラム
struct ListNode* reverseList(struct ListNode* head)
{
if (head == NULL || head->next == NULL) //链表为空或者仅1个数直接返回
return head;
struct ListNode* p,*newH;
p=head;
newH=NULL;
while (p)
{
struct ListNode* q;
q= p->next;
p->next = newH;
newH = p;
p = q;
}
return newH;
}
2.再帰的に
- 我々は、非再帰的な方法の前に、達成する反転再帰的なリストを見ては後の処理に続いて数1の前方から開始することで、再帰的に、対照的に、それは最初のサイクル数5の最後方の点を発見し、次いで5から注文の処理を開始しますリスト全体を反転させます。
- 第一の端部における反復ポインタH、以下に示すように、反転後のリンクされたリストの先頭として、新しいポインタを設定します。最後の番号を反転させた後、リスト全体の長として、そのプロセス全体は、収納スペース5に対処するためにNewHポインタポイントとなっています。
- その後、ポインタH層によって層とは、下図の処理を行うために戻ってきたとき、アドレスを割り当てるH H-指さ>ネクスト>次のポインタ、およびH-を作るために必ず覚えておいてください>次= NULL、今切断ポインタでありますリンク、またはリングが新しいリストを形成し、次の層H->ネクスト>次回以降の値をカバーするために割り当てられます。
- 操作を返すように続けます。
- 図は、スペース割り当て4 NULL、第H->ネクスト>次= Hを指す最初の次のポインタなしで保存され、それはすべて混乱ようにアドレス空間5は、3で覆われて保存されます。そして、1件の取引のためのアドレス空間まで、層によって層を下に戻します。
- 頭を返します:
- 再帰的プログラム
struct ListNode* reverseList(struct ListNode* head)
{
if (head == NULL || head->next == NULL)
return head;
struct ListNode* newHead = reverseList(head->next);
head->next->next = head;
head->next = NULL;
return newHead;
}
3.最初のノードの反転リスト
- トピック説明:/ *旅を横断するアルゴリズムを設計し、鎖方向のすべてのリンクが逆転され、空間の元の使用は、まだテーブル* /
- 考え:第1のチェーン・ポインタ・フィールドブランキングの最初のノードが、リンクされたリストの最初のノードは、pによって指さ; Q * pが後続点を、* Pその後、ヘッドノードに挿入されます。
void TurnList(LinkList &L)
{
struct LNode *p;
p = L->next;
L->next = NULL;
while (p)
{
LNode *q;
q = p->next; // q指向*p的后继
p->next = L->next;
L->next = p; // 将*p插入到头结点之后
p = q;
}
}
- コードの実装
- main.cppに
#include<iostream>
using namespace std;
typedef struct LNode
{
int data;
struct LNode *next;
}LNode, *LinkList;
int InitList(LinkList &L)
{
L = new LNode;
L->next = NULL;
return 1;
}
void TraveList(LinkList L)
{
LNode *p;
p = L->next;
printf("遍历链表:\n");
while (p)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
//前插法创建单链表
void CreateList(LinkList &L, int n)
{
L = new LNode;
L->next = NULL;
for (int i = n; i > 0; --i)
{
printf("请输入第%d个元素的值:", i);
struct LNode *p;
p = new LNode;
scanf("%d", &p->data);
p->next = L->next;
L->next = p;
}
}
/*
思想:
先将链表的头结点指针域置空,p指向链表的第一个结点;
q指向*p的后继,然后将*p插入到头结点的后面。
*/
void TurnList(LinkList &L)
{
struct LNode *p;
p = L->next;
L->next = NULL;
while (p)
{
LNode *q;
q = p->next; // q指向*p的后继
p->next = L->next;
L->next = p; // 将*p插入到头结点之后
p = q;
}
}
int main()
{
LinkList L;
if (InitList(L))
{
printf("链表初始化成功!\n");
}
else
{
printf("链表初始化失败!\n");
}
printf("请输入链表的长度:\n");
int n;
scanf("%d", &n);
CreateList(L, n);
TraveList(L);
printf("反转后的链表:\n");
TurnList(L);
TraveList(L);
system("pause");
return 0;
}
- 業績