C++で連結リスト内のすべての0を先頭に移動する方法
問題の概要
ランダムな整数と0を含む連結リストが与えられます。この問題では、リスト内のすべての0を連結リストの先頭に移動させる必要があります。具体的な例を見てみましょう。
入力
3 -> 0 -> 1 -> 0 -> 0 -> 1 -> 0 -> 0 -> 3 -> NULL
出力
0->0->0->0->0->3->1->1->3->NULL
出力を見ると、すべての0がリストの先頭に集められ、それ以外の要素は元の相対的な順序を保ったまま後ろに並んでいることがわかります。
アルゴリズム
- 連結リストを初期化します。
- 連結リストが空、またはノードが1つしかない場合は、そのまま処理を終了します。
- 現在のノードと前のノードを追跡するため、それぞれ2番目のノードと先頭のノードで2つのポインタを初期化します。
- 連結リストの末尾に到達するまで反復処理を行います。
- 現在のノードの値が0である場合、そのノードを新しい先頭(ヘッド)にします。ノードを新しい先頭にすることで、自動的にリストの先頭へ移動されます。このとき、新しい先頭のnextポインタを、それまでの先頭ノードで更新します。その後、現在のノードと前のノードの変数の値を適切に更新します。
実装
以下は、上記のアルゴリズムをC++で実装したコードです。
#include <bits/stdc++.h>
using namespace std;
struct Node {
int data;
struct Node *next;
};
void addNewNode(struct Node **head, int data) {
struct Node *newNode = new Node;
newNode->data = data;
newNode->next = *head;
*head = newNode;
}
void moveZeroes(struct Node **head) {
if (*head == NULL) {
return;
}
struct Node *temp = (*head)->next, *prev = *head;
while (temp != NULL) {
if (temp->data == 0) {
Node *current = temp;
temp = temp->next;
prev->next = temp;
current->next = *head;
*head = current;
} else {
prev = temp;
temp = temp->next;
}
}
}
void printLinkedList(struct Node *head) {
while (head != NULL) {
cout << head->data << "->";
head = head->next;
}
cout << "NULL" << endl;
}
int main() {
struct Node *head = NULL;
addNewNode(&head, 3);
addNewNode(&head, 0);
addNewNode(&head, 1);
addNewNode(&head, 0);
addNewNode(&head, 0);
addNewNode(&head, 1);
addNewNode(&head, 0);
addNewNode(&head, 0);
addNewNode(&head, 3);
moveZeroes(&head);
printLinkedList(head);
return 0;
}
実行結果
上記のコードをコンパイルして実行すると、以下の結果が得られます。
0->0->0->0->0->3->1->1->3->NULL
計算量
このアルゴリズムは連結リストを一度だけ走査するため、時間計算量はO(n)です。また、追加のメモリを使用しないため、空間計算量はO(1)となります。ポインタの付け替えだけでノードを移動できるのが、連結リストならではの利点と言えるでしょう。
-
【C++】循環リンクリストのノード値の合計を求める方法
この記事では、循環リンクリスト(Circular Linked List)が与えられたときに、すべてのノードの値の合計を求めるプログラムをC++で作成する方法を解説します。 やるべきことはシンプルで、リンクリストを構成する全ノードの値を順番に読み取り、それらを加算していくだけです。 前提知識:重要な定義 リンクリストとは リンクリスト(連結リスト)とは、各データ(ノード)をポインタによるリンクで相互に接続したデータ構造の列です。配列と異なり、メモリ上の連続した領域を必要とせず、動的な挿入や削除に強いという特徴があります。 循環リンクリストとは 循環リンクリストはリンクリストの変形の一種で、先
-
C++で連結リストの交互ノードの合計を求める方法(反復法・再帰法)
問題概要 この記事では、連結リスト(リンクリスト)が与えられたときに、その交互ノード(0、2、4…番目のノード)の値の合計を求める方法を解説します。 連結リストとは、リンク(ポインタ)によって順次接続されたデータ構造の列です。各ノードはデータ本体と、次のノードを指す参照を持っています。 今回の課題は、連結リストのうち位置 0、2、4、6 … にあるノード、つまり先頭から1つおきのノードの値をすべて加算することです。 入出力例 入力: 4 → 12 → 10 → 76 → 9 → 26 → 1 出力: 24 説明: 交互ノードを取り出すと − 4 + 10 + 9 + 1 = 24 解決の考