C++でソート済み双方向リンクリストを実装するプログラムと解説
リンクリスト(連結リスト)とは
データ構造におけるリンクリスト(連結リスト)は、データ要素を線形に並べた集合です。リストの各要素(ノード)は「データ」と「次のノードへの参照(ポインタ)」という2つの項目で構成され、最後のノードはnullへの参照を持ちます。リンクリストへの入口となる先頭ノードは「ヘッド(head)」と呼ばれます。
双方向リンクリストとは
双方向リンクリスト(ダブルリンクリスト)は、ノードと呼ばれるレコードが順次連結されたデータ構造です。各ノードは3つのフィールドを持ちます。1つはデータフィールド、残りの2つはリンクフィールドで、それぞれノード列における「前のノード」と「次のノード」への参照を保持します。これにより、リストを前方向にも後ろ方向にもたどることができます。
ソート済み双方向リンクリスト
ソート済み双方向リンクリストでは、データフィールドの値に基づいて、リストが常にソートされた状態に保たれます。新しいノードを挿入する際には適切な位置を探索して挿入するため、リスト全体の順序が崩れることはありません。
アルゴリズム
始まり
createnode() 関数:リストにノードを挿入する
新しいノードを生成し、そのデータフィールドに数値を格納する。
リストが空かどうかを判定する。空の場合は、そのノードを最初の要素として配置し、head を更新する。
prev と next の両ポインタを NULL で初期化する。
リストが空でない場合は、リスト全体がソートされた状態を保てるように、新しいノードを既存のリンクリストの適切な位置に挿入する。
prev と next のポインタを適宜更新する。
終わり
始まり
display_head() 関数:head からリストを表示する
c = 0 で初期化する。
ポインタ変数を head ノードのアドレスで初期化する。
while (c <= i)
ノードの情報を表示する
ポインタ変数を更新する
c をインクリメントする
終わり
始まり
display_tail() 関数:tail からリストを表示する
m = 0 で初期化する。
ポインタ変数を tail ノードのアドレスで初期化する。
while (m <= i)
ノードの情報を表示する
ポインタ変数を更新する
m をインクリメントする
終わりサンプルコード
以下は、C++でソート済み双方向リンクリストを実装したサンプルコードです。ノードを挿入するたびに適切な位置へ配置することで、リスト全体が常にソートされた状態に保たれます。
#include<iostream>
using namespace std;
struct nod {
int d;
nod *n, *p;
}
*p = NULL, *head = NULL, *r = NULL, *np = NULL, *tail = NULL;
int c = 0;
void createnode(int n) {
np = new nod;
np->d = n;
np->n = NULL;
np->p = NULL;
if (c == 0) {
tail = np;
head = np;
p = head;
p->n = head;
p->p = head;
c++;
} else if (c == 1) {
p = head;
r = p;
if (np->d < p->d) {
np->n = p;
p->p = np;
head = np;
p->n = np;
np->p = p;
tail = p;
} else if (np->d > p->d) {
p->n = np;
np->p = p;
np->n= head;
p->p = np;
}
c++;
} else {
p = head;
r = p;
if (np->d < p->d) {
np->n = p;
p->p = np;
head = np;
do {
p = p->n;
}
while (p->n != r);
tail = p;
p->n = np;
np->p = p;
} else if (np->d > p->d) {
while (p->n != head && np->d > p->d) {
r = p;
p = p->n;
if (p->n == head && (p->d < np->d)) {
p->n = np;
np->p = p;
np->n = head;
tail = np;
head->p = np;
break;
} else if (np->d< p->d) {
r->n= np;
np->p = r;
np->n= p;
p->p= np;
if (p->n != head) {
do {
p = p->n;
}
while (p->n != head);
}
tail = p;
break;
}
}
}
}
}
void display_head(int i) {
nod *t = head;
int c = 0;
while (c <= i) {
cout<<t->d<<"\t";
t = t->n;
c++;
}
cout<<endl;
}
void display_tail(int i) {
nod *t = tail;
int m = 0;
while (m <= i) {
cout<<t->d<<"\t";
t = t->p;
m++;
}
cout<<endl;
}
int main() {
int i = 0, n, a, ch;
cout<<"enter the no of nodes\n";
cin>>n;
while (i < n) {
cout<<"\nenter value of node\n";
cin>>a;
createnode(a);
i++;
}
cout<<"\nsorting Doubly Linked List head first\n";
display_head(n);
cout<<"\nsorting Doubly Linked List tail first\n";
display_tail(n);
}実行結果
enter the no of nodes 5 enter value of node 7 enter value of node 4 enter value of node 6 enter value of node 2 enter value of node 1 sorting Doubly Linked List head first 1 2 4 6 7 1 sorting Doubly Linked List tail first 7 6 4 2 1 7
このプログラムでは、head(先頭)から順に表示した結果と、tail(末尾)から逆順に表示した結果の両方を出力しています。なお、表示ループの条件が c <= i となっているため、要素数より1回多くループが回り、循環リストとして先頭の値が末尾に1つだけ続けて表示される点に注意してください。
-
C++で双方向リンクリストのサイズ(要素数)を求めるプログラム
本記事では、双方向リンクリスト(Doubly Linked List)が与えられたときに、そのサイズ(要素数)を求めるC++プログラムの作成方法を詳しく解説します。 双方向リンクリストとは、片方向リンクリストと比べて、各ノードが前後両方向のリンクを持つため、前方にも後方にも自由に移動できる特殊なリンクリストです。まず、双方向リンクリストを理解するうえで重要な用語を確認しておきましょう。 リンク(Link):リンクリストの各リンクには、「要素」と呼ばれるデータが格納されます。 ネクスト(Next):各リンクには、次のリンクを指す参照「Next」が含まれます。 プレヴ(Prev):各リンクに
-
C++でグラフの隣接リストを実装する方法:サンプルコード付きで解説
グラフの隣接リストは、連結リスト(リンクリスト)を用いたグラフの表現方法の一つです。この表現では、リストを要素とする配列を使用し、その配列のサイズは V(頂点の総数)となります。言い換えれば、V個の異なるリストを格納するための配列を用意することになります。各リストの先頭が頂点 u に対応しており、そのリストには「頂点 u に隣接するすべての頂点」が格納されます。 隣接リスト表現の計算量 無向グラフの場合、必要な記憶領域は O(V + 2E)、有向グラフの場合は O(V + E) となります。 辺の数が増加すると、それに伴って必要なメモリ量も増えていきます。そのため、辺の密度が低い(スパースな