C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++で連結リストを交互に2つのリストへ分割する再帰的アプローチ

片方向連結リストが入力として与えられたとき、元のリストのノードを交互に振り分けた2つの片方向連結リストに分割することを目標とします。例えば、入力リストのノードが a → b → c → d → e → f という並びである場合、分割後の2つのサブリストは「a → c → e」と「b → d → f」になります。

この問題では、2つのポインタ N1 と N2 を用意します。N1 は元のリストの先頭ノードを、N2 は先頭の次のノードを指すようにします。その後、両方のポインタを「次の次」のノードへ順に移動させながら、それぞれのサブリストを構築していきます。

具体例

入力 − リスト: 1 → 5 → 7 → 12 → 2 → 96 → 33

出力
元のリスト: 1 5 7 12 2 96 33
リスト1: 1 7 2 33
リスト2: 5 12 96

解説 − 先頭の 1 と 5 から処理を開始し、交互のノードをたどることで上記の2つのサブリストを作成します。

入力 − リスト: 13 → 53 → 90 → 18 → 44 → 11 → 99 → 32

出力
元のリスト: 13 53 90 18 44 11 99 32
リスト1: 13 90 44 99
リスト2: 53 18 11 32

解説 − 先頭の 13 と 53 から処理を開始し、交互のノードをたどることで上記の2つのサブリストを作成します。

プログラムで使用するアプローチ

このアプローチでも、2つのポインタ N1 と N2 を用意し、一方は元のリストの先頭を、もう一方は先頭の次のノードを指すようにします。その後、両方のポインタを「次の次」のノードへ移動させながらサブリストを作成します。具体的な手順は以下のとおりです。

  • int 型のデータ部分と、次ノードへのポインタ next を持つ構造体 Node を定義します。
  • 関数 addtohead(Node** head, int data) は、リストの先頭にノードを追加して片方向連結リストを構築するために使用します。
  • 上記の関数を使い、head を先頭ノードへのポインタとして片方向連結リストを作成します。
  • 関数 display(Node* head) は、先頭ノードから順にリンクリストの内容を出力するために使用します。
  • 2つの Node ポインタ node1 と node2 を用意します。
  • 関数 splitList(Node* head, Node** n1, Node** n2) はノードポインタを受け取り、n1 を元のリストの先頭に、n2 を先頭の次のノードに設定します。
  • その内部で split(*n1, *n2) を呼び出し、元のリストを2つのサブリストに分割します。
  • 関数 split(Node* N1, Node* N2) は N1 と N2 のポインタを受け取り、元のリストの交互のノードを含む2つのサブリストを作成します。
  • N1 と N2 のどちらかが NULL の場合は、何もせずに処理を終了します。
  • N1→next が NULL でない場合、tmp = N1->next->next として N1->next = tmp を設定します。
  • N2→next が NULL でない場合も同様に、tmp = N2->next->next として N2->next = tmp を設定します。
  • split(N1->next, N2->next); を呼び出して、次のノードペアの処理へ再帰的に進みます。
  • 最後に display() を使って、分割後のサブリストを出力します。

実装例

#include <bits/stdc++.h>
using namespace std;
struct Node {
   int data;
   struct Node* next;
};
void addtohead(Node** head, int data){
   Node* nodex = new Node;
   nodex->data = data;
   nodex->next = (*head);
   (*head) = nodex;
}
void split(Node* N1, Node* N2){
   Node *tmp;
   if (N1 == NULL || N2 == NULL){
      return;
   }
   if (N1->next != NULL){
      tmp=N1->next->next;
      N1->next = tmp;
   }
   if (N2->next != NULL){
      tmp=N2->next->next;
      N2->next = tmp;
   }
   split(N1->next, N2->next);
}
void splitList(Node* head, Node** n1, Node** n2){
   *n1 = head;
   *n2 = head->next;
   split(*n1, *n2);
}
void display(Node* head){
   Node* curr = head;
   if (curr != NULL){
      cout<<curr->data<<" ";
      display(curr->next);
   }
}
int main(){
   Node* head = NULL;
   Node *node1 = NULL, *node2 = NULL;
   addtohead(&head, 20);
   addtohead(&head, 12);
   addtohead(&head, 15);
   addtohead(&head, 8);
   addtohead(&head, 10);
   addtohead(&head, 4);
   addtohead(&head, 5);

   cout<<"Original List :"<<endl;
   display(head);
   splitList(head, &node1, &node2);
   cout<<endl<<"List 1: ";
   display(node1);
   cout<<endl<<"List 2: ";
   display(node2);
   return 0;
}

出力結果

上記のコードを実行すると、次のような出力が得られます。

Original List :
5 4 10 8 15 12 20
List 1: 5 10 15 20
List 2: 4 8 12
  1. C++で連結リストの交互ノードの合計を求める方法(反復法・再帰法)

    問題概要 この記事では、連結リスト(リンクリスト)が与えられたときに、その交互ノード(0、2、4…番目のノード)の値の合計を求める方法を解説します。 連結リストとは、リンク(ポインタ)によって順次接続されたデータ構造の列です。各ノードはデータ本体と、次のノードを指す参照を持っています。 今回の課題は、連結リストのうち位置 0、2、4、6 … にあるノード、つまり先頭から1つおきのノードの値をすべて加算することです。 入出力例 入力: 4 → 12 → 10 → 76 → 9 → 26 → 1 出力: 24 説明: 交互ノードを取り出すと − 4 + 10 + 9 + 1 = 24 解決の考

  2. C++の連結リストを使って2つの多項式を加算する方法

    この概念をより深く理解するために、まず必要な基本事項をおさらいしましょう。連結リスト(Linked List)とは連結リストは、各要素を「ノード」と呼ばれるオブジェクトとして格納するデータ構造です。各ノードは、データ部分と次のノードへのリンクの2つの要素で構成されています。多項式(Polynomial)とは多項式とは、変数と係数から構成される数学的な式のことです。例えば、x2 − 4x + 7 のようなものが該当します。多項式を表す連結リスト多項式連結リストでは、多項式の係数と指数がリストのデータノードとして定義されます。連結リストとして格納された2つの多項式を加算するには、同じ次数(べき乗)