リンクされたリストの概念は、現実の世界でよく使用されます。私たちが学んだ単一リンクリストの概念は、Spotify を使用してキュー内の次の曲を再生するときに役立ちます。しかし、キュー内の前の曲を再生するには具体的にどうすればよいでしょうか?
このブログでは、データ構造に関連するもう 1 つの概念、つまり二重リンク リストについて学びます。C 言語を使用した実装やリアルタイム アプリケーションについても説明します。
二重リンクリストとは何ですか?
リンク リストは、連続的に接続されたノードを含む線形データ構造です。ノードには 3 つのフィールド、つまり参照アドレスに格納されているデータと、参照ノードの左右の後続ノードへの 2 つのポインタが含まれています。
左側のノード ポインタにはシーケンス内の前のノードのメモリ アドレスが格納され、右側のノードには次のノードのメモリ アドレスが格納されます。ここでは、実行される操作に応じて実行時にメモリ サイズを割り当てたり割り当て解除したりできるように、配列の代わりに動的メモリ割り当てを使用します。
この例では、ヘッドは最初のノードを指します。参照ノードの左ポインタには、最後のノードの右ポインタと同様に NULL が格納されます。
この例を操作するには、さらに進んで、対応する変更を加えることができます。
二重リンクリストの実装
1. ノードを前に挿入します
上記の操作を実行するには、まずノードを作成し、動的メモリを使用してメモリを割り当てます。頭を新しいノードに向け、左右のノードに NULL 値を格納します。
void front_add(){
//allocate memory using dynamic memory allocation.
newnode -> data = NULL;
newnode -> prev = NULL;
newnode -> next = head;
head= newnode;
}
2. フロントノードを削除します
先頭からノードを削除するには、ヘッド内の参照アドレスの正しいノード値を格納し、最初のノードを解放する必要があります。
void front_del(){
newnode=head;
head= head->next ;
head->prev = NULL;
free(newnode);
}
3. 最後にノードを挿入します
最後にノードを追加するには、最後までたどり、最後のノードが参照される新しいノードを指すようにする必要があり、その逆も同様です。
void end_add(){
//allocate memory to newnode
newnode -> data= item; // temp=head
while(temp ->next !=NULL)
{
temp = temp->next;
}
temp->next= newnode;
newnode -> prev = temp;
newnode-> next = NULL;
}
4. 終了ノードの削除
最後のノードを削除するには、リンクされたリストをたどって最後に到達する必要があります。最後の 2 番目のノードへのポインターを使用します。次に、最後のノードを解放します。
void rear_del(){
while(temp -> next!=NULL)
{
temp = temp->next; //temp=head
}
temp ->prev-> next = NULL;
free(temp);
}
基本的な操作を理解したので、次に C で二重リンクリストを段階的に実装していきます。
#include<stdio.h>
#define MAX 5
struct node{
int data;
struct node * prev;
struct node * next;
};
struct node *head;
void front_add();
void front_del();
void rear_add();
void rear_del();
void display();
int main(){
int choice=0;
while(choice!=6){
printf("enter choice:\n");
printf("\n1.front_add\n2.front_Del\n3.rear_add\n4.rear_del\n5.display\n6.exit");
scanf("%d\n",&choice);
switch(choice){
case 1:
front_add();
break;
case 2:
front_del();
break;
case 3:
rear_add();
break;
case 4:
rear_del();
break;
case 5:
display();
break;
case 6:
printf("exiting...\n");
break;
default:
printf("unknown choice\n");
}
}
}
void front_add(){
struct node* newnode;
int item;
newnode = (struct node*)malloc(sizeof(struct node));
printf("enter item value:\n");
scanf("%d", &item);
if(head == NULL)
{
newnode -> next = NULL;
newnode -> prev = NULL;
newnode -> data = item;
head = newnode;
}
else
{
newnode -> data = item;
newnode -> prev = NULL;
newnode -> next = head;
head->prev = newnode;
head= newnode;
}
}
void front_del(){
struct node *newnode;
if(head->next == NULL)
{
head = NULL;
free(head);
printf("\nnode deleted\n");
}
else
{
newnode=head;
head= head->next ;
head->prev = NULL;
free(newnode);
printf("deleted\n");
}
}
void rear_add(){
struct node *temp,*newnode;
int item;
newnode = (struct node*)malloc(sizeof(struct node));
printf("enter item");
scanf("%d", &item);
newnode -> data= item;
temp = head;
while(temp ->next !=NULL)
{
temp = temp->next;
}
temp->next= newnode;
newnode -> prev = temp;
newnode-> next = NULL;
printf("inserted\n");
}
void rear_del(){
struct node *temp;
temp=head;
if(head->next==NULL)
{
head = NULL;
free(head);
printf("deleted\n");
}
else{
while(temp -> next!=NULL)
{
temp = temp->next;
}
temp ->prev-> next = NULL;
free(temp);
printf("deleted\n");
}
}
void display(){
struct node *temp;
temp = head;
if(head==NULL)
{
printf("empty\n");
}
else{
while(temp!=NULL)
{
printf("%d", temp->data);
temp = temp->next;
}
}
}
このコードにより、目的の出力が得られます。
プレイヤーが繰り返しのループでチャンスを得るこのようなマルチプレイヤー ゲームがどのように開発されているのか疑問に思ったことはありますか? これは、最後のプレーヤーが再び最初のプレーヤーにリンクされてループを形成することを意味します。
これを可能にするために、リンク リストに関連する別の概念を導入します。この場合、循環リンク リストが役立ちます。
循環リンクリスト
循環単一リンク リストでは、リンク リストの最後のノードには、リンク リストの最初のノードへのポインタが含まれます。二重リンクリストと単一リンクリストの両方でこの概念を使用できます。
このリストと他の 2 つのリストの唯一の違いは、最後のノードの右ポインタが最初のノードを指すのに対し、ヘッド ノードは常に最初のノード自体を指すことです。
結論は
私の意見では、リンク リストの概念は非常に重要であり、複雑な問題を解決するのに役立ちます。二重リンク リストと循環単一リンク リストは、さまざまなシナリオを実行するときに連携して使用されます。このブログを楽しんで読んでいただければ幸いです。今日のトピックに関するご意見に「いいね」とコメントをお願いします。楽しく学習しましょう!!