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

C++で連結リストのピーク要素を見つけるアルゴリズムを解説

このチュートリアルでは、C++を使って与えられた連結リスト(リンクリスト)からピーク要素を見つけるプログラムを作成します。

ピーク要素とは、両隣の要素(前後の要素)よりも大きい値を持つ要素のことです。それでは、問題を解くための手順を順番に見ていきましょう。

アルゴリズムの手順

  • 連結リスト用のノード構造体(struct Node)を定義します。

  • ダミーデータを使って連結リストを構築します。

  • 連結リストが空、または要素数が1の場合など、ベースケース(境界条件)を先にチェックします。

  • 最初の要素の値を変数 prev(前の要素)として保存しておきます。

  • 連結リストを先頭から走査します。

    • 現在の要素が、前の要素と次の要素のどちらよりも大きいかどうかを判定します。

    • 条件を満たしていれば、その値をピーク要素として返します。

    • 条件を満たさない場合は、prev を現在の要素の値で更新して次へ進みます。

  • 最後に結果を出力します。

なお、リストの末尾は「次の要素」が存在しないため、ループ終了後に末尾の要素とその前の要素を比較し、末尾が大きければそれもピーク要素となります。すべてのチェックで該当する要素が見つからなかった場合は -1 を返す仕様にしています。

サンプルコード

それでは、実際のコードを見てみましょう。

#include <bits/stdc++.h>
using namespace std;
struct Node {
   int data;
   struct Node* next;
};
void insertNewNode(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;
}
int findPeakElement(struct Node* head) {
   if (head == NULL) {
      return -1;
   }
   if (head->next == NULL) {
      return head->data;
   }
   int prev = head->data;
   Node *current_node;
   for (current_node = head->next; current_node->next != NULL; current_node = current_node->next) {
      if (current_node->data > current_node->next->data && current_node->data > prev) {
         return current_node->data;
      }
      prev = current_node->data;
   }
   if (current_node->data > prev) {
      return current_node->data;
   }
   return -1;
}
int main() {
   struct Node* head = NULL;
   insertNewNode(&head, 7);
   insertNewNode(&head, 4);
   insertNewNode(&head, 5);
   insertNewNode(&head, 2);
   insertNewNode(&head, 3);
   cout << findPeakElement(head) << endl;
   return 0;
}

実行結果

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

5

コードの解説

この例では、連結リストは 3 → 2 → 5 → 4 → 7 の順で構成されています。走査を進めると、値 5 が前の要素 2 および次の要素 4 のどちらよりも大きいため、5 が最初に見つかったピーク要素として返されます。

計算量についても触れておくと、リストを一度だけ走査するため時間計算量は O(n)、補助的なメモリ使用量は O(1) となり、非常に効率的なアルゴリズムです。

まとめ

このチュートリアルでは、C++における連結リストからピーク要素を見つける方法を学びました。ベースケースの処理やリスト末尾の扱いなど、実装時の注意点も押さえておくことで、より堅牢なコードになります。

本チュートリアルについて質問がある場合は、コメント欄でお気軽にお知らせください。

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

    単一リンクリストが与えられたとき、値が素数になっているノードをすべて見つけ出し、それらの値の積を計算して出力するのが本稿のテーマです。ここで「素数ノード」とは、データ部分に素数を格納しているノードを指します。 入力例 85 → 6 → 7 → 2 → 10 出力例 14 説明 リストを先頭から順に調べると、85 は 5×17 に分解できるため素数ではなく除外されます。6 も 2×3 であり除外、続く 7 は素数なので採用、2 も素数なので採用、最後の 10 は 2×5 であるため除外されます。したがって積は 7 × 2 = 14 となります。 解決のた

  2. C++で双方向リンクリストのサイズ(要素数)を求めるプログラム

    本記事では、双方向リンクリスト(Doubly Linked List)が与えられたときに、そのサイズ(要素数)を求めるC++プログラムの作成方法を詳しく解説します。 双方向リンクリストとは、片方向リンクリストと比べて、各ノードが前後両方向のリンクを持つため、前方にも後方にも自由に移動できる特殊なリンクリストです。まず、双方向リンクリストを理解するうえで重要な用語を確認しておきましょう。 リンク(Link):リンクリストの各リンクには、「要素」と呼ばれるデータが格納されます。 ネクスト(Next):各リンクには、次のリンクを指す参照「Next」が含まれます。 プレヴ(Prev):各リンクに