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

C言語プログラムで単一リンクリスト(片方向連結リスト)のノードの合計を求める方法

片方向リンクリストとは

片方向リンクリスト(単一リンクリスト)は、各要素(ノード)が「データの値」と「次のノードへのリンク(ポインタ)」という2つの部分で構成されるデータ構造です。リンクリスト内のすべての要素の合計を求めるには、先頭ノードから順に各ノードをたどりながら、その値を合計用の変数に加算していきます。

具体例

リンクリスト: 2 -> 27 -> 32 -> 1 -> 5
合計 = 2 + 27 + 32 + 1 + 5 = 67

合計を求める2つの方法

リンクリストのノードの合計を求めるには、大きく分けて次の2つの方法があります。

  • 方法1:ループ(反復処理)を使ってリンクリストのすべての値を走査し、合計を求める
  • 方法2:再帰関数を使って、リンクリストに要素がなくなるまで自分自身を呼び出しながら合計を求める

方法1:ループを使う方法

ループはリンクリストの末尾、つまりノードのポインタがNULLを指すまで実行され、その間に各ノードの値を順次加算していきます。処理がシンプルで追加のメモリをほとんど消費しないため、最も一般的な実装方法です。

サンプルコード(ループ版)

#include <iostream>
using namespace std;
struct Node {
    int data;
    struct Node* next;
};
void push(struct Node** nodeH, int nodeval) {
    struct Node* new_node = new Node;
    new_node->data = nodeval;
    new_node->next = (*nodeH);
    (*nodeH) = new_node;
}
int main() {
    struct Node* head = NULL;
    int sum = 0;
    push(&head, 95);
    push(&head, 60);
    push(&head, 87);
    push(&head, 6);
    push(&head, 12);
    struct Node* ptr = head;
    while (ptr != NULL) {
        sum += ptr->data;
        ptr = ptr->next;
    }
    cout << "Sum of nodes = " << sum;
    return 0;
}

実行結果

Sum of nodes = 260

方法2:再帰関数を使う方法

再帰関数は、リンクリストに要素が存在する限り自分自身を繰り返し呼び出します。各呼び出しでは、次のノードへのポインタと、合計値を格納する変数のアドレスを引数として渡します。コードが簡潔になる反面、再帰の深さ分だけスタックメモリを消費する点に注意が必要です。

サンプルコード(再帰版)

#include <bits/stdc++.h>
using namespace std;
struct Node {
    int data;
    struct Node* next;
};
void push(struct Node** head_ref, int new_data) {
    struct Node* new_node = new Node;
    new_node->data = new_data;
    new_node->next = (*head_ref);
    (*head_ref) = new_node;
}
void nodesum(struct Node* head, int* sum) {
    if (!head)
        return;
    nodesum(head->next, sum);
    *sum = *sum + head->data;
}
int main() {
    struct Node* head = NULL;
    int sum = 0;
    push(&head, 95);
    push(&head, 60);
    push(&head, 87);
    push(&head, 6);
    push(&head, 12);
    nodesum(head, &sum);
    cout << "Sum of nodes = " << sum;
    return 0;
}

実行結果

Sum of nodes = 260

計算量の比較

どちらの方法も全ノードを一度ずつ訪問するため、時間計算量はO(n)で同一です。ただし、ループ版の空間計算量はO(1)であるのに対し、再帰版は呼び出しスタックをノード数分だけ使用するためO(n)となります。ノード数が非常に多いリンクリストを扱う場合は、スタックオーバーフローを避けるためにもループ版の採用が推奨されます。

補足

なお、本記事のコード例はC++(new演算子やiostreamを使用)で記述しています。純粋なC言語で実装する場合は、ノードの確保にmalloc()を、結果の出力にprintf()を使用してください。

  1. 【C++】循環リンクリストのノード値の合計を求める方法

    この記事では、循環リンクリスト(Circular Linked List)が与えられたときに、すべてのノードの値の合計を求めるプログラムをC++で作成する方法を解説します。 やるべきことはシンプルで、リンクリストを構成する全ノードの値を順番に読み取り、それらを加算していくだけです。 前提知識:重要な定義 リンクリストとは リンクリスト(連結リスト)とは、各データ(ノード)をポインタによるリンクで相互に接続したデータ構造の列です。配列と異なり、メモリ上の連続した領域を必要とせず、動的な挿入や削除に強いという特徴があります。 循環リンクリストとは 循環リンクリストはリンクリストの変形の一種で、先

  2. C++で連結リストの交互ノードの合計を求める方法(反復法・再帰法)

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