二重リンクリストの関連操作
それらはすべて私自身の実践とアイデアです。間違いがある場合は、指摘してください。修正します。
成長する愛好家は一生懸命働き続けます
単一リンクリスト:各ノードは(データフィールド+ポインタフィールド)であり、ノードのクエリを容易にします。単一リンクリスト内の各ノードのポインタは次のノードを指すデータフィールドであるため、ノードの前のノードのデータをクエリするのは非常に不便です。したがって、単一リンクリストはデータのバックチェックには不便です。
二重リンクリスト:単一リンクリスト(データフィールド+ポインタフィールド)と同じノードですが、単一リンクリストとは異なり、二重リンクリストの各ノードには次のノードと前のノードへのポインタがあります。同時にノード、それが前任者であるかどうか、そしてリアドライブ要素は非常に便利です
したがって、要素の二重リンクリストを取得するためのより多くの利点があります
1>二重リンクリストを定義する
#include<stdio.h>
typedef struct DNode
{
int data;//存放每个节点的数据
int *prior, *next;//一个指向前驱节点的指针,一个指向后驱节点的指针
}DNode,*DLinkList;//对这个结构体重新命名为Dnode,并用DLinkList指向这个结构体
void main()
{
DLinkList L;//创建一个双链表
}
DNode、* DLinkLisは、単一リンクリストと同様に、typedefを使用してこの構造の名前をDnodeに変更し、DLinkListを使用してこの構造をポイントします(単一リンクリストの投稿ですでに説明したtypedefの意味と機能)
2つのポインタ* prior(adj:previous; Early; first; priority; first; moreimportant; before;この定義は、より高い可読性と実用性を備えています。 *次の意味によると次のノードへのポインタであることがわかります。
ヘッドノードへのポインタLは、main関数mainで宣言されています。
2>二重リンクリストを初期化する
リードノードの初期化
初期化する前に、まずヘッドノードにスペースを割り当てる必要があります。割り当てが成功したかどうかを判断するにはどうすればよいですか。
分析:二重リンクリストは最初は空である必要があります。テーブルのヘッドノードには後続ノードのみがあり、先行ノードはなく、終了ノードには後続ノードのみがあり、先行ノードはありません。
これからわかります:(L-> previous = NULL; //ヘッドノードに先行要素がありませんL-> next = NULL; //二重リンクリストは最初は空です)
void InitDLinkList(DLinkList&L)//带头节点
{
L = (DNode*)malloc(sizeof(DNode));//为头节点分配空间
if (L == NULL)
{
printf("抱歉为空,分配失败!");
}
else {
L->prior = NULL;//头节点是没有前驱元素的
L->next = NULL;//初始时双链表为空表
printf("初始化成功!\n");
}
}
3>二重リンクリストにデータを追加する
シングルリンクリストと同様に、ダブルリンクリストにデータを追加するには、2つのポインタノードが必要です。1つは現在のノードのデータを保存し、もう1つはノードの場所を指します。
初期状態では、二重リンクリストのヘッダーは空であり、先行要素はありません。
D-> next = P-> next; //次のノードに移動
P-> next = D; // Dは2番目のノードになります
D-> prior = P; // 2番目のノードは先行ノード
Pを指します= D; // Dが最初のノードになります
Dにスペースを割り当てた後、D-> dataのデータフィールドに値を割り当てることができます。Dノードのテールポインタをヘッドノードのテールポインタにポイントする方法(ヘッドポインタはP、フロントポインタは空)、Dをヘッドとして使用できます。ポインターの後の最初のノードは、DのフロントポインターをヘッドポインターPにどのようにポイントしますか?最後にP = D、最初のノードのデータが入力されます
void CreatDLinkList(DLinkList &L)//双链表输入数据
{
DNode *D, *P;
L=(DNode*)malloc(sizeof(DNode));//为头节点分配空间
L->next = NULL;//初始状态下双链表为空表
P = L;//现在P就是头节点
P->prior = NULL;//头节点的前驱是为空的
int n;//输入数据的数量
printf("请输入双链表元素的数量:");
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
D = (DLinkList)malloc(sizeof(DNode));//为存储数据的指针分配空间
printf("data[%d]=",i);
scanf("%d",&D->data);//第一个节点的数据已经存储到D中
D->next = P->next;//定位到下一个节点
P->next =D;//D现在为第二个节点
D->prior = P;//第二个节点指向前驱节点
P = D;//D成为第一个节点
}
}
4>二重リンクリストの長さを取得する
主にデータの数を数える変数を定義します
p = l-> nextは、ヘッドノードの後の最初のノードへのポインタを定義し、次に二重リンクリストをトラバースし、空でない場合はループを続行します
void GetLength(DLinkList L)//获取双链表长度
{
DNode*P;//开辟一个节点
P = (DNode*)malloc(sizeof(DNode));//分配空间
P = L->next;
int length = 0;
while(P!=NULL)
{
length++;
P = P->next;
}
printf("双链表的长度为%d\n",length);
}
5>二重リンクリストの挿入(ビット単位)
二重リンクリストの各ノードには前後に2つのポインターがありますが、挿入は同じです。補間後でも補間前でも、最初にi-1(i)番目の要素を見つけるだけで済みます。次にそれをリンクします。
シングルリンクリストとは異なり、ダブルリンクリストの挿入にはさらにいくつかの手順が必要です。これはフロントポインタのリンクに関するものです。
アイデアを正すとわかりやすくなりますので、紙とペンで描いたり書いたりすることをお勧めします(単一のリンクリストは類推できます)
重要な点は、i-1番目がテールノードである場合、それがテールノードである場合、P-> nextは(P-> next-> previous = S)でNULLになると考えることです。だからあなたは望ましい結果を得ることができません
void InsertDLinkList(DLinkList &L, int i,int e)//插入有头节点
{
GetLength(L);
if (i < 1)
{
printf("插入位置不合法");
}
else {
DNode* P;//查询的数据的节点(遍历节点)
int number = 0;//记录位序
P = L;//P指向头节点,现在P就是头节点
while (P != NULL && number < i - 1)
{
P = P->next;//找到第i-1个节点位置
number++;
}
if(P==NULL)
{
printf("插入失败,插入前驱节点数据异常");
}
else {
DNode *S = (DNode*)malloc(sizeof(DNode));//保持插入数据的节点
S->data = e;//接收插入数据大S节点
S->next = P->next;//将插入元素的指针指向第i个节点
if (P->next!=NULL)//这里主要考虑的是最后一个节点
{
P->next->prior = S;//P->next代表第i个节点,P->next->prior代表第i个节点的前指针
}
S->prior = P;//再将S的前指针指向第i-1个节点
P->next = S;//最后将第i-1个节点的后指针指向插入节点
printf("插入数据%d到第%d个节点完成",e,i);
}
}
}
6>二重リンクリストを削除する
私が書いたのは基本的にビット単位の削除なので、肥大化したように見えます。この書き込みの目的は、論理関係の理解を容易にすることでもあります(単一リンクリストと同じように、最初にi-1番目のノードを見つけます->次にポインタを-に変更します->スペースノードを解放します->操作を完了します)
i-1ノードとiノードを判断する必要があります。i-1がすでにテールノードである場合、iが存在しないというエラーが報告される可能性があります。同様に、p-> next(i番目のノードに相当)が空の場合、削除されたノードがテールノードであることを意味します。そのため、i-1ノードを直接変更し、ポインターをNULLにして、iノード。最後のケースで、iがテールノードでない場合は、通常どおりポインタを変更します。
void DeletDLinkList(DLinkList&L,int i)//删除节点i(按位)
{
if (i < 0)
printf("抱歉删除位置不合法!\n");
DNode* P;//查询的数据的节点(遍历节点)
int number = 0;//记录位序
P = L;//P指向头节点,现在P就是头节点
while (P != NULL && number < i - 1)
{
P = P->next;//找到第i-1个节点位置
number++;
}
if (P == NULL)
{
printf("数据为空,删除失败");//如果i-1节点已经位空,则i节点一定为空
}
else {
DNode *S = (DNode*)malloc(sizeof(DNode));//定义删除数据的节点
S = P->next;//S现在代表就是第i节点
if (S == NULL)//如果i-1是尾节点
{
printf("删除失败,删除节点位空");
}
else {
P->next = S->next;//将i-1节点的后指针指向i+1节点
if (S->next != NULL)//说明i不是最后一个节点
{
S->next->prior = P;
free(S);//释放掉节点s
}
printf("删除第%d个节点成功",i);
}
}
}
7>二重リンクリストの検索(ビット単位/値単位)
単一リンクリストのように見つけることの本質はトラバーサルです
forループかwhileループかに関係なく、メインの内部ループ条件が設定されます。前提条件が設定されていると仮定すると、L-> nextを同時に指すポインターノードPがあります。
トラバース:二重リンクリスト全体をトラバースできるように、P!= nullを設定するだけです。
ビット単位:ビット単位とトラバーサルの違いは、カウント変数を設定することです(int i = 0-> i = query node position)
値によって:長い上プレスへの結合部位とトラバースのように、現在のノード一つずつ比較します
void GetElem(DLinkList L, int i)//按位查找
{
if (i < 0)
printf("查询位置不合法");
DNode *P;//定义一个指针,代表每个节点的数据
P = L->next;//P指向头节点后的第一个节点
int number=1;//计数变量
while (P != NULL&&number<i)
{
number++;
P = P->next;//继续向下一个节点移动
}
printf("查询第%d个元素为%d",i,P->data);
}
値で検索
void GetELem_value(DLinkList L, int e)//按值查找
{
DNode *P;//定义一个指针,代表每个节点的数据
P = L->next;//P指向头节点后的第一个节点
int number = 1;//计数变量
while (P != NULL && P->data!=e)
{
number++;
P = P->next;//继续向下一个节点移动
}
if (P = NULL)//跳出循环说明双链表中不含该数据
{
printf("抱歉双链表中没有该数据\n");
}
printf("双链表中含有数据%d个位置为%d\n",e,number);
}
したがって、要約すると、ビット単位と値は基本的に同じです。
8>全体的なコード
#include<stdio.h>
#include<stdlib.h>
typedef struct DNode
{
int data;//存放每个节点的数据
struct DNode *prior, *next;//一个指向前驱节点的指针,一个指向后驱节点的指针
}DNode,*DLinkList;//对这个结构体重新命名为Dnode,并用DLinkList指向这个结构体
void InitDLinkList(DLinkList&L)//带头节点
{
L = (DNode*)malloc(sizeof(DNode));//为头节点分配空间
if (L == NULL)
{
printf("抱歉为空,分配失败!");
}
else {
L->prior = NULL;//头节点是没有前驱元素的
L->next = NULL;//初始时双链表为空表
printf("初始化成功!\n");
}
}
void CreatDLinkList(DLinkList &L)//双链表输入数据
{
DNode *D, *P;
L=(DNode*)malloc(sizeof(DNode));//为头节点分配空间
L->next = NULL;//初始状态下双链表为空表
L->next = NULL;//头节点的前驱是为空的
P = L;//现在P就是头节点
int n;//输入数据的数量
printf("请输入双链表元素的数量:");
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
D = (DLinkList)malloc(sizeof(DNode));//为存储数据的指针分配空间
printf("data[%d]=",i);
scanf("%d",&D->data);//第一个节点的数据已经存储到D中
D->next = P->next;//定位到下一个节点
P->next =D;//D现在为第二个节点
D->prior = P;//第二个节点指向前驱节点
P = D;//D成为第一个节点
}
}
void GetLength(DLinkList L)//获取双链表长度
{
DNode*P;//开辟一个节点
P = (DNode*)malloc(sizeof(DNode));//分配空间
P = L->next;
int length = 0;
while(P!=NULL)
{
length++;
P = P->next;
}
printf("\n双链表的长度为%d\n",length);
}
void InsertDLinkList(DLinkList &L, int i,int e)//插入有头节点
{
GetLength(L);
if (i < 1)
{
printf("插入位置不合法");
}
else {
DNode* P;//查询的数据的节点(遍历节点)
int number = 0;//记录位序
P = L;//P指向头节点,现在P就是头节点
while (P != NULL && number < i - 1)
{
P = P->next;//找到第i-1个节点位置
number++;
}
if(P==NULL)
{
printf("插入失败,插入前驱节点数据异常");
}
else {
DNode *S = (DNode*)malloc(sizeof(DNode));//定义插入数据的节点
S->data = e;//接收插入数据大S节点
S->next = P->next;//将插入元素的指针指向第i个节点
if (P->next!=NULL)//这里主要考虑的是最后一个节点
{
P->next->prior = S;//P->next代表第i个节点,P->next->prior代表第i个节点的前指针
}
S->prior = P;//再将S的前指针指向第i-1个节点
P->next = S;//最后将第i-1个节点的后指针指向插入节点
printf("插入数据%d到第%d个节点完成",e,i);
}
}
}
void DeletDLinkList(DLinkList&L,int i)//删除节点i(按位)
{
if (i < 0)
printf("抱歉删除位置不合法!\n");
DNode* P;//查询的数据的节点(遍历节点)
int number = 0;//记录位序
P = L;//P指向头节点,现在P就是头节点
while (P != NULL && number < i - 1)
{
P = P->next;//找到第i-1个节点位置
number++;
}
if (P == NULL)
{
printf("数据为空,删除失败");//如果i-1节点已经位空,则i节点一定为空
}
else {
DNode *S = (DNode*)malloc(sizeof(DNode));//定义删除数据的节点
S = P->next;//S现在代表就是第i节点
if (S == NULL)//如果i-1是尾节点
{
printf("删除失败,删除节点位空");
}
else {
P->next = S->next;//将i-1节点的后指针指向i+1节点
if (S->next != NULL)//i不是最后一个节点
{
S->next->prior = P;
free(S);//释放掉节点s
}
printf("删除第%d个节点成功",i);
}
}
}
void GetElem(DLinkList L, int i)//按位查找
{
if (i < 0)
printf("查询位置不合法");
DNode *P;//定义一个指针,代表每个节点的数据
P = L->next;//P指向头节点后的第一个节点
int number=1;//计数变量
while (P != NULL&&number<i)
{
number++;
P = P->next;//继续向下一个节点移动
}
printf("查询第%d个元素为%d",i,P->data);
}
void GetELem_value(DLinkList L, int e)//按值查找
{
DNode *P;//定义一个指针,代表每个节点的数据
P = L->next;//P指向头节点后的第一个节点
int number = 1;//计数变量
while (P != NULL && P->data!=e)
{
number++;
P = P->next;//继续向下一个节点移动
}
if (P = NULL)//跳出循环说明双链表中不含该数据
{
printf("抱歉双链表中没有该数据\n");
}
printf("双链表中含有数据%d个位置为%d\n",e,number);
}
void ShowDLinkList(DLinkList L)//打印双链表
{
DNode *P;//定义一个指针,代表每个节点的数据
P = (DNode*)malloc(sizeof(DNode));//为节点分配空间
P = L->next;//P指向头节点后的第一个节点
int i=0;//记录位序
printf("打印双链表\n");
while (P!=NULL)
{
printf("data[%d]=%d\n",i,P->data);
i++;
P = P->next;//继续向下一个节点移动
}
}
void main()
{
DLinkList L;//创建一个双链表
InitDLinkList(L);//初始化
CreatDLinkList(L);//输入数据
InsertDLinkList(L,5,99);//插入元素按位
DeletDLinkList(L,5);//删除节点按位
GetLength(L);//获取双链表长度
GetElem(L,5);//按位查询
GetELem_value(L,45);//按值查找
ShowDLinkList(L);//打印双链表
}