C++で2つのソート済み連結リストをマージする方法【サンプルコード付き】
問題の概要
ソート済みの単方向連結リストが2つ与えられます。この2つのリストを1つのソート済みリストに統合(マージ)する関数を作成してください。
List1: 10->15->17->20 List2: 5->9->13->19 Result: 5->9->10->13->15->17->19->20
アルゴリズム
基本的な考え方は、両方のリストを先頭から順に走査し、常に値の小さい方のノードを結果リストにつなげていくというものです。
1. 両方のリストを走査する 1.1. list1->data < list2->data の場合 1.1.1 結果リストにlist1->dataを追加し、list1のポインタを進める 1.2. list2->data < list1->data の場合 1.2.1 結果リストにlist2->dataを追加し、list2のポインタを進める 2. 両方のリストが尽きるまで手順を繰り返す 3. 結果のリストを返す
C++での実装例
以下は、再帰的なアプローチを用いて2つのソート済み連結リストをマージするC++プログラムの完全な例です。
#include <iostream>
#include <new>
#define SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
using namespace std;
struct node {
int data;
struct node *next;
};
node *createList(int *arr, int n){
node *head, *p;
p = head = new node;
head->data = arr[0];
head->next = NULL;
for (int i = 1; i < n; ++i) {
p->next = new node;
p = p->next;
p->data = arr[i];
p->next = NULL;
}
return head;
}
void displayList(node *head){
while (head != NULL) {
cout << head->data << " ";
head = head->next;
}
cout << endl;
}
node *mergeSortedLists(node *head1, node *head2){
node *result = NULL;
if (head1 == NULL) {
return head2;
}
if (head2 == NULL) {
return head1;
}
if (head1->data < head2->data) {
result = head1;
result->next = mergeSortedLists(head1->next, head2);
} else {
result = head2;
result->next = mergeSortedLists(head1, head2->next);
}
return result;
}
int main(){
int arr1[] = {10, 15, 17, 20};
int arr2[] = {5, 9, 13, 19};
node *head1, *head2, *result = NULL;
head1 = createList(arr1, SIZE(arr1));
head2 = createList(arr2, SIZE(arr1));
cout << "First sorted list: " << endl;
displayList(head1);
cout << "Second sorted list: " << endl;
displayList(head2);
result = mergeSortedLists(head1, head2);
cout << "Final sorted list: " << endl;
displayList(result);
return 0;
}出力結果
上記のプログラムをコンパイルして実行すると、次のような出力が得られます。
First sorted list: 10 15 17 20 Second sorted list: 5 9 13 19 Final sorted list: 5 9 10 13 15 17 19 20
コードのポイント
この実装では、mergeSortedLists関数が再帰的に呼び出され、2つのリストの先頭ノード同士を比較しながら、値の小さい方から順に結果リストへつなげていきます。どちらか一方のリストが空になった時点で、もう一方の残りのリストがそのまま返されるため、マージ処理が完了します。
このアルゴリズムの計算量は O(n + m)(n と m はそれぞれのリストの長さ)です。新しいノードを生成せず既存のノードを再利用するため、追加のメモリ消費がほとんどない効率的な手法と言えます。
-
C++で2つの二分木をマージする方法
2つの二分木があるとします。一方の木をもう一方の木に重ねてみると、一部のノードは互いに重なり合い、残りのノードは重ならない状態になります。ここで、この2つの木を1つの新しい二分木へマージすることを考えます。マージのルールは次のとおりです。2つのノードが重なっている場合は、それらの値を合計したものをマージ後のノードの新しい値とします。どちらか一方しかノードが存在しない場合は、空でない方のノードをそのまま新しい木のノードとして使用します。たとえば、次のような2つの木が与えられたとします。このときの出力結果は以下のようになります。解法のアプローチこの問題を解くために、以下の手順に従います。メソッド名
-
C++の連結リストを使って2つの多項式を加算する方法
この概念をより深く理解するために、まず必要な基本事項をおさらいしましょう。連結リスト(Linked List)とは連結リストは、各要素を「ノード」と呼ばれるオブジェクトとして格納するデータ構造です。各ノードは、データ部分と次のノードへのリンクの2つの要素で構成されています。多項式(Polynomial)とは多項式とは、変数と係数から構成される数学的な式のことです。例えば、x2 − 4x + 7 のようなものが該当します。多項式を表す連結リスト多項式連結リストでは、多項式の係数と指数がリストのデータノードとして定義されます。連結リストとして格納された2つの多項式を加算するには、同じ次数(べき乗)