C++で2つの片方向リンクリストに共通するノードを検索して数える方法
2つの片方向リンクリスト(単一リンクリスト)が与えられたとき、両方のリストに共通して存在するノードの総数を求める問題を考えてみましょう。例えば、2つのリストが [15, 16, 10, 9, 7, 17] と [15, 16, 40, 6, 9] の場合、共通する値は「15」「16」「9」の3つであるため、共通ノードの数は 3 となります。
アルゴリズムの考え方
最も基本的なアプローチは、ネストした2つのループを使って両方のリストを走査する方法です。具体的には以下の手順で処理を行います。
- 最初のリストの各ノードについて、2番目のリスト内のいずれかのノードとデータが一致するかどうかを順番にチェックします。
- 一致するノードが見つかった場合、カウンターを1つ増やし、2番目のリストの探索を打ち切って次のノードへ進みます(同じノードを二重にカウントしないため)。
- すべてのノードに対して比較が完了したら、カウンターの値を結果として返します。
この手法では、リストの長さをそれぞれ 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」が出力されます。
-
C++で連結リストの交互ノードの合計を求める方法(反復法・再帰法)
問題概要 この記事では、連結リスト(リンクリスト)が与えられたときに、その交互ノード(0、2、4…番目のノード)の値の合計を求める方法を解説します。 連結リストとは、リンク(ポインタ)によって順次接続されたデータ構造の列です。各ノードはデータ本体と、次のノードを指す参照を持っています。 今回の課題は、連結リストのうち位置 0、2、4、6 … にあるノード、つまり先頭から1つおきのノードの値をすべて加算することです。 入出力例 入力: 4 → 12 → 10 → 76 → 9 → 26 → 1 出力: 24 説明: 交互ノードを取り出すと − 4 + 10 + 9 + 1 = 24 解決の考
-
C++で循環リンクリストのノード数をカウントする方法
ノードから構成される循環リンクリスト(Circular Linked List)が与えられ、そのリスト内に存在するノードの総数を求めるのが課題です。 循環リンクリストとは、連結リストの一種であり、最初の要素が最後の要素を指し、最後の要素が最初の要素を指すという特徴を持つデータ構造です。片方向リンクリスト(Singly Linked List)でも双方向リンクリスト(Doubly Linked List)でも、この循環リンクリストとして実装することが可能です。 以下のプログラムでは、片方向リンクリストを循環リンクリストとして実装し、その中に含まれるノード数をカウントする方法を紹介します。 具体