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

C++で単一リンクリスト内のすべての素数ノードの積を求める方法


単一リンクリストが与えられたとき、値が素数になっているノードをすべて見つけ出し、それらの値の積を計算して出力するのが本稿のテーマです。ここで「素数ノード」とは、データ部分に素数を格納しているノードを指します。

入力例

85 → 6 → 7 → 2 → 10

出力例

14

説明

リストを先頭から順に調べると、85 は 5×17 に分解できるため素数ではなく除外されます。6 も 2×3 であり除外、続く 7 は素数なので採用、2 も素数なので採用、最後の 10 は 2×5 であるため除外されます。したがって積は 7 × 2 = 14 となります。

解決のためのアプローチ

  • node 型の一時ポインタ(temp など)を用意します。

  • そのポインタを、ヘッドポインタが指す先頭ノードに設定します。

  • temp を temp→next へ進めながら、各ノードの値が素数かどうかを判定していきます。

  • 値が素数であれば、product = product × (temp→data) を実行して積を更新します。

  • 素数でなければ何もせず、次のノードへ進みます。

  • リストの末尾に到達したら、product 変数の最終値を出力します。

アルゴリズム

Start
Step 1 → リストに挿入するノードの構造体を作成
    struct node
        int data;
        node* next
    End
Step 2 → ノードをリストに挿入する関数を宣言
    void push(node** head_ref, int data)
        Set node* newnode = (node*)malloc(sizeof(struct node))
        Set newnode→data = data
        Set newnode→next = (*head_ref)
        Set (*head_ref) = newnode
    End
Step 3 → 素数かどうかを判定する関数を宣言
    bool isPrime(int data)
        IF data <= 1
            return false
        End
        IF data <= 3
            return true
        End
        IF data % 2 == 0 || data % 3 == 0
            return false
        Loop For int i = 5 and i * i <= data and i = i + 6
            IF data % i == 0 || data % (i + 2) == 0
                return false
            End
        End
        return true
Step 4 → 積を計算する関数を宣言
    void product(node* head_ref)
        set int product = 1
        set node* ptr = head_ref
        While ptr != NULL
            IF (isPrime(ptr→data))
                Set product *= ptr→data
            End
            Set ptr = ptr→next
        End
        Print product
Step 5 → main() 内での処理
    node* head = NULL を宣言
    Call push(&head, 10)
    Call push(&head, 2)
    Call product(head)
Stop

なお、isPrime 関数では「6k±1 法」という最適化手法を採用しています。2 と 3 の倍数をあらかじめ除外した上で、5 から始めて 6 ずつ増やしながら i と i+2 の両方で割り切れるかを確認することで、平方根 O(√n) の範囲で効率よく素数判定が可能になります。

C++コード例

#include <bits/stdc++.h>
using namespace std;
// ノードの構造体
struct node{
    int data;
    node* next;
};
// ノードを挿入する関数
void push(node** head_ref, int data){
    node* newnode = (node*)malloc(sizeof(struct node));
    newnode→data = data;
    newnode→next = (*head_ref);
    (*head_ref) = newnode;
}
// 数が素数かどうかを判定する関数
bool isPrime(int data){
    if (data <= 1)
        return false;
    if (data <= 3)
        return true;
    if (data % 2 == 0 || data % 3 == 0)
        return false;
    for (int i = 5; i * i <= data; i = i + 6)
        if (data % i == 0 || data % (i + 2) == 0)
            return false;
    return true;
}
// 素数ノードの積を求める関数
void product(node* head_ref){
    int product = 1;
    node* ptr = head_ref;
    while (ptr != NULL){
        if (isPrime(ptr→data)){
            product *= ptr→data;
        }
        ptr = ptr→next;
    }
    cout << \"連結リスト内のすべての素数ノードの積 = \" << product;
}
int main(){
    node* head = NULL;
    push(&head, 10);
    push(&head, 2);
    push(&head, 7);
    push(&head, 6);
    push(&head, 85);
    product(head);
    return 0;
}

出力

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

連結リスト内のすべての素数ノードの積 = 14

計算量について

リンクリストの長さを n、ノードが取りうる最大値を m とすると、リスト全体の走査に O(n)、各ノードの素数判定に O(√m) が必要となるため、全体の時間計算量は O(n√m) となります。補助的な領域はポインタ 1 個分だけで済むため、空間計算量は O(1) です。

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

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

  2. C++で循環リンクリストのノード数をカウントする方法

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