データ構造 - 二重リンクリスト

権力者の恩恵を求めるよりも、自分の力で未来を切り拓きたい 

記事ディレクトリ

二重線リンクリストの各インターフェースの関数名または変数名 

二重リンクリストインターフェース実装ソースコード

クイックインデックス [ヘッダーファイルと関数宣言]

二重リンクリストインターフェイスの実装

二重連結リストの構成解析

二重リンクリストの定義と初期化

二重リンクリストの挿入と削除


過去のレビュー:

データ構造 - 単一リンクリスト

データ構造 - 配列リスト

  皆さんこんにちは、ジニンです。

  この記事では、単一リンク リストよりもパフォーマンスが優れたリンク リスト、つまりデータの挿入、削除、検索をより効率的に実装できる二重リンク リストについて紹介します。

  記事の前半は二重リンクリストの対応する名前とソースコード、記事の後半は二重リンクリストの実装の具体的な説明です。

二重線リンクリストの各インターフェースの関数名または変数名 

LTデータタイプ 二重リンクリストのデータ型の名前変更
リストノード 二重リンクリスト構造
LTノード 二重リンクリストの名前変更
LTノードを購入する ノードを作成する
LTI ノードを初期化する
LTプリント 二重リンクリストを印刷する
LTPプッシュバック テールプラグ
LTポップバック 末尾削除
LTPushFront プラグ
LTポップフロント 頭の削除
LTサイズ 二重リンクリスト要素の数を計算する
LTFind リンクされたリスト要素を検索する
LT挿入 pos の前にノードを挿入
LTErase 位置 pos のノードを削除します

二重リンクリストインターフェース実装ソースコード

クイックインデックス [ヘッダーファイルと関数宣言]

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int LTDataType;//重命名

typedef struct ListNode
{
	LTDataType Data;
	struct ListNode* next;
	struct ListNode* prev;
}LTNode;
LTNode* BuyLTNode(LTDataType x); //创建一个新节点
LTNode* LTInit(); //哨兵位的头结点
void LTPrint(LTNode*phead);//打印双链表
void LTPushBack(LTNode* phead, LTDataType x);//尾插
void LTPopBack(LTNode* phead);//尾删
void LTPushFront(LTNode* phead, LTDataType x);//头插
void LTPopFront(LTNode* phead);//头删
LTNode* LTFind(LTNode* phead, LTDataType x);//寻找结点
void LTInsert(LTNode*phead,LTNode* pos, LTDataType x); //在pos之前插入结点

二重リンクリストインターフェイスの実装

LTNode* BuyLTNode(LTDataType x)
{
	LTNode* nownode =(LTNode*)malloc(sizeof(LTNode));
	if (nownode == NULL)
	{
		perror("malloc fail");
	}
	nownode->Data = x;
	nownode->next = NULL;
	nownode->prev = NULL;
	return nownode;
}

LTNode* LTInit()
{
	LTNode* phead = BuyLTNode(0);
	phead->next = phead;
	phead->prev = phead;
	return phead;
}

void LTPushBack(LTNode* phead, LTDataType x)
{
	assert(phead);
	LTNode* tail = phead->prev;
	LTNode* nownode = BuyLTNode(x);
	nownode->next = phead;
	nownode->prev = tail;
	tail->next = nownode;
	phead->prev = nownode;
}

void LTPrint(LTNode* phead)
{
	assert(phead);
	printf("phead<=>");
	LTNode* cur = phead;
	while (cur->next!=phead)
	{
		printf("%d<=>", cur->next->Data);
		cur = cur->next;
	}
	printf("\n");
}

void LTPopBack(LTNode* phead)
{
	assert(phead);
	assert(phead->next != phead);//只有哨兵位的时候不能删
	LTNode* tail = phead->prev;
	LTNode* tailPrev = tail->prev;
	tailPrev->next = tail->next;
	phead->prev = tailPrev;
	free(tail);
}
void LTPushFront(LTNode* phead, LTDataType x)
{
	assert(phead);
	LTNode* first = phead->next;
	LTNode* nownode = BuyLTNode(x);
	nownode->next = first;
	nownode->prev = phead;
	phead->next = nownode;
	first->prev = nownode;
}

void LTPopFront(LTNode* phead)
{
	assert(phead);
	assert(phead->next != phead);//只有哨兵位的时候不能删除
	LTNode* first = phead->next;
	LTNode* second = first->next;
	phead->next = second;
	second->prev = phead;
	free(first);
}

LTNode* LTFind(LTNode* phead, LTDataType x)
{
	assert(phead);
	LTNode* cur = phead;
	while (cur->next != phead)
	{
		if (cur->next->Data == x)
			return  cur->next;
		cur = cur->next;
	}
	return NULL;
}

void LTInsert(LTNode* phead, LTNode* pos, LTDataType x)
{
	assert(phead);
	assert(pos);
	LTNode* cur = phead;
	while (cur->next != pos)
	{
		cur = cur->next;
	}
	LTNode*nownode = BuyLTNode(x);
	nownode->next = pos;
	nownode->prev = cur;
	cur->next = nownode;
	pos->prev = nownode;
}

void LTErase(LTNode* phead, LTNode* pos)
{
	assert(pos&&phead);
	assert(pos->next != pos);
	assert(phead->next != phead);
	LTNode* cur = phead;
	LTNode* posNext = pos->next;
	while (cur->next != pos)
	{
		cur = cur->next;
	}
	cur->next = posNext;
	posNext->prev = cur;
	free(pos);
}

二重連結リストの構成解析

  二重リンク リストは、単一リンク リストと比較して、二重リンク リストのノードには 2 つのポインター ドメインがあり、1 つは次のノードを指し、もう 1 つは前のノードを指します。デフォルトの二重リンク リストにはセンチネル ビットを持つヘッド ノードがあります。センチネル ビットの先頭 ノードは、最初の有効なノードのアドレス (phead->next) と最後の有効なノードのアドレス (phead->prev) を格納します。

シングルリンクリストとダブルリンクリストの論理図の比較

シングルリンクリストとダブルリンクリストの物理図の比較

二重リンクリストの定義と初期化

  二重リンクリストにはデータフィールドと 2 つのポインタフィールドがあり、1 つのポインタは次のノードのアドレスを指し、もう 1 つのポインタは前のノードのアドレスを指し、二重リンクリストの構造は再び名前が変更されます。

  二重リンク リストが新しいノードを開くときは、まずノード サイズのスペースを開き、その次の NULL を空にポイントしてから、データ フィールドの値を x に割り当てる必要があります。

二重リンクリストの挿入と削除

  二重リンク リストを削除するには、まずセンチネル ビットのヘッド ノードは削除できないことを明確にします。これは、二重リンク リスト全体の構造サポートであるためです。削除するときは、削除するノードの前のノードと次のノードを見つけて、前のノードの次のポインタを次のノードにポイントし、次のノードの prev ポインタを前のノードにポイントします。最後に、削除されたノードのスペースが解放されます。

  二重リンクリストの挿入では、理論的には任意の位置にノードを挿入できます。初期化時には、新しく作成されたノードを定義するポインター フィールドはすべて空であるためです。したがって、挿入するときは、挿入されたノードの 2 つのポインタ フィールドを変更し、その next ポインタが次のノードを指すようにし、その prev ポインタが前のノードを指すようにする必要があります。同様に、前のノードの next ポインタがこの新しいノードを指し、next ポインタの prev ポインタがこの新しいノードを指します。

おすすめ

転載: blog.csdn.net/zyb___/article/details/132063876