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

C++で2つの片方向リンクリストに共通するノードを検索して数える方法

2つの片方向リンクリスト(単一リンクリスト)が与えられたとき、両方のリストに共通して存在するノードの総数を求める問題を考えてみましょう。例えば、2つのリストが [15, 16, 10, 9, 7, 17][15, 16, 40, 6, 9] の場合、共通する値は「15」「16」「9」の3つであるため、共通ノードの数は 3 となります。

アルゴリズムの考え方

最も基本的なアプローチは、ネストした2つのループを使って両方のリストを走査する方法です。具体的には以下の手順で処理を行います。

  1. 最初のリストの各ノードについて、2番目のリスト内のいずれかのノードとデータが一致するかどうかを順番にチェックします。
  2. 一致するノードが見つかった場合、カウンターを1つ増やし、2番目のリストの探索を打ち切って次のノードへ進みます(同じノードを二重にカウントしないため)。
  3. すべてのノードに対して比較が完了したら、カウンターの値を結果として返します。

この手法では、リストの長さをそれぞれ n、m とすると、計算量は O(n × m) になります。シンプルで分かりやすい反面、大規模なリストには不向きなため、実用場面ではハッシュセットを併用して O(n + m) に高速化することも可能です。

サンプルコード(C++)

#include<iostream>
using namespace std;
class Node {
   public:
      int data;
   Node *next;
};
// リストの先頭に新しいノードを挿入する関数
void prepend(Node** start, int new_data) {
   Node* new_node = new Node;
   new_node->data = new_data;
   new_node->next = NULL;
   if ((*start) != NULL){
      new_node->next = (*start);
      *start = new_node;
   }
   (*start) = new_node;
}
// 共通ノードの数を数える関数
int countCommonNodes(Node** start1, Node** start2) {
   Node* ptr = *start1;
   Node* ptr1 = *start2;
   int count = 0;
   while (ptr != NULL) {
      while (ptr1 != NULL) {
         if (ptr->data == ptr1->data) {
            count++;
            break;
         }
         ptr1 = ptr1->next;
      }
      ptr1 = *start2; // 2番目のリストのポインタを先頭に戻す
      ptr = ptr->next;
   }
   return count;
}
int main() {
   Node* first = NULL;
   Node* second = NULL;
   // 1つ目のリストを作成
   prepend(&first, 15);
   prepend(&first, 16);
   prepend(&first, 10);
   prepend(&first, 9);
   prepend(&first, 7);
   prepend(&first, 17);
   // 2つ目のリストを作成
   prepend(&second, 15);
   prepend(&second, 16);
   prepend(&second, 40);
   prepend(&second, 6);
   prepend(&second, 9);
   cout << "Number of common nodes:" << countCommonNodes(&first, &second);
}

実行結果

Number of common nodes:3

このプログラムでは、prepend() 関数によって各リストの先頭にノードを追加しながらリストを構築し、countCommonNodes() 関数で二重ループによる全件比較を行っています。その結果、2つのリストに共通するノード数として「3」が出力されます。

  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++で循環リンクリストのノード数をカウントする方法

    ノードから構成される循環リンクリスト(Circular Linked List)が与えられ、そのリスト内に存在するノードの総数を求めるのが課題です。 循環リンクリストとは、連結リストの一種であり、最初の要素が最後の要素を指し、最後の要素が最初の要素を指すという特徴を持つデータ構造です。片方向リンクリスト(Singly Linked List)でも双方向リンクリスト(Doubly Linked List)でも、この循環リンクリストとして実装することが可能です。 以下のプログラムでは、片方向リンクリストを循環リンクリストとして実装し、その中に含まれるノード数をカウントする方法を紹介します。 具体