C++で連結リストの長さを求める方法(反復処理と再帰処理の両アプローチ)
この記事では、反復(イテレーティブ)と再帰(リカーシブ)という2つの異なるアプローチを用いて、C++で連結リストの長さを求める方法を詳しく解説します。リストの先頭ポインタが与えられている場合、以下の手順に従うことでノード数を正確に取得できます。
反復アプローチの手順
- リストの先頭ノードから処理を開始します。
- 現在のポインタがNULLでない間、次のノードへ移動し、そのたびにカウントを1増やしていきます。
- ポインタがNULLになった時点でのカウント値が、リスト全体の長さとなります。
再帰アプローチの手順
- 先頭ノードを引数として関数に渡します。
- 基本条件(ベースケース)は「引数がNULLの場合は0を返す」ことです。
- それ以外の場合は、現在のノードの次のノードを引数として自分自身を再帰的に呼び出します。
- 戻り値は「1 + 部分リストの長さ」となり、これによって全体のノード数が計算されます。
コード例
#include<iostream>
using namespace std;
class Node {
public:
int data;
Node* next;
};
void append(struct Node** start, int data) {
struct Node* new_node = new Node;
new_node->data = data;
new_node->next = (*start);
(*start) = new_node;
}
int count_recursive(Node* start) {
if (start == NULL)
return 0;
return 1 + count_recursive(start->next);
}
int count_iterative(Node* start) {
int count = 0;
Node* current = start;
while (current != NULL) {
count++;
current = current->next;
}
return count;
}
int main() {
Node* start = NULL;
append(&start, 1);
append(&start, 3);
append(&start, 1);
append(&start, 2);
append(&start, 1);
cout << "Node count using iterative approach: " << count_iterative(start) << endl;
cout << "Node count using recursion: " << count_recursive(start);
}
実行結果
Node count using iterative approach: 5 Node count using recursion: 5
両アプローチの比較
どちらの手法も時間計算量は O(n) で同じですが、空間計算量に違いがあります。
- 反復アプローチ: 空間計算量は O(1)。追加のメモリをほとんど消費せず、スタックオーバーフローの心配がないため、大きなリストに対しても安全に使えます。
- 再帰アプローチ: 呼び出しスタックを使用するため、空間計算量は O(n)。コードは簡潔で読みやすい反面、リストが非常に長い場合はスタックオーバーフローを引き起こすリスクがある点に注意が必要です。
実務では安全性と効率の観点から反復アプローチが推奨されることが多いですが、再帰の考え方を理解しておくことは、木構造などより複雑なデータ構造を扱う際にも役立ちます。
-
C++で二分木の完全ノードを数える方法(反復法と再帰法)
本記事では、二分木に含まれる「完全ノード(フルノード)」の数を、反復法と再帰法の2つのアプローチで求める方法を解説します。完全ノードとは、左と右の子を両方持ち、どちらの子もNULLでないノードのことです。つまり、ちょうど2つの子を持つノードのみが完全ノードとして扱われます。 二分木はデータの格納に用いられる特殊なデータ構造です。「各ノードが最大2つの子までしか持てない」という制約があり、ソート済み配列並みの高速な検索性能と、連結リスト並みの高速な挿入・削除性能を兼ね備えているのが特徴です。なお、1つ以上の子を持つ非葉ノードは「親ノード」とも呼ばれます。 二分木の基本構造は以下の通りです。
-
C++で二分木の半ノード(ハーフノード)を数える方法【反復・再帰の両アプローチ】
本記事では、二分木(バイナリツリー)に含まれる「半ノード(ハーフノード)」の数を、反復処理と再帰処理の2つのアプローチで求める方法を解説します。半ノードとは?半ノードとは、子を1つだけ持ち、もう片方の子がNULL(空)になっているノードのことです。なお、子をまったく持たない葉ノードは半ノードには含まれない点に注意してください。二分木はデータの格納に使われる特殊なデータ構造です。各ノードが最大2つの子を持つという制約があり、ソート済み配列並みの高速な検索と、連結リスト並みの高速な挿入・削除の両方を実現できるというメリットがあります。二分木の基本的な構造は以下の通りです。具体例入力:出力: カウン