데이터 구조 - 이중 연결 리스트

나는 권력자들의 총애를 구하는 것보다 내 힘으로 미래를 개척하겠다. 

기사 디렉토리

이중 연결 목록의 각 인터페이스의 함수 이름 또는 변수 이름 

이중 연결 목록 인터페이스 구현 소스 코드

빠른 색인 [헤더 파일 및 함수 선언]

이중 연결 목록 인터페이스 구현

이중 연결 목록의 구성 분석

이중 연결 리스트 정의 및 초기화

이중 연결 리스트 삽입 및 삭제


지난 리뷰:

데이터 구조 - 단일 연결 목록

데이터 구조 - 서열 목록

  안녕하세요 여러분, 저는 지닝입니다.

  이 기사에서는 단일 연결 목록보다 더 나은 성능을 제공하는 연결 목록, 즉 데이터 삽입, 삭제 및 검색을 보다 효율적으로 구현할 수 있는 이중 연결 목록을 소개합니다.

  기사의 전반부는 이중 연결 목록의 해당 이름과 소스 코드이고, 기사의 후반부는 이중 연결 목록의 구현에 대한 구체적인 설명입니다.

이중 연결 목록의 각 인터페이스의 함수 이름 또는 변수 이름 

LT데이터 유형 이중 연결 목록 데이터 유형 이름 바꾸기
목록노드 이중 연결리스트 구조
LT노드 이중 연결 리스트 이름 바꾸기
BuyLTNode 노드를 생성하다
LTI 노드 초기화
LTPrint 이중 연결리스트 인쇄
LTP푸시백 테일 플러그
LT팝백 꼬리 삭제
LTPushFront 플러그
LT팝프론트 헤드 삭제
LT크기 이중 연결 목록 요소 수 계산
LT찾기 연결리스트 요소 찾기
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);
}

이중 연결 목록의 구성 분석

  이중 연결 목록은 단일 연결 목록과 비교하여 이중 연결 목록의 노드에는 두 개의 포인터 도메인이 있는데, 하나는 다음 노드를 가리키고 다른 하나는 이전 노드를 가리키며, 기본 이중 연결 목록에는 센티널 비트가 있는 헤드 노드가 있습니다. 센티넬 비트의 헤드 노드는 첫 번째 유효한 노드의 주소(phead->next)와 마지막 유효한 노드의 주소(phead->prev)를 저장합니다.

단일 및 이중 연결 목록 논리 다이어그램 비교

단일 및 이중 연결 목록의 물리적 다이어그램 비교

이중 연결 리스트 정의 및 초기화

  이중 연결 리스트에는 데이터 필드와 두 개의 포인터 필드가 있는데, 하나의 포인터는 다음 노드의 주소를 가리키고, 하나의 포인터는 이전 노드의 주소를 가리키며, 이중 연결 리스트의 구조는 다시 이름이 변경됩니다.

  이중 연결 리스트가 새 노드를 열면 먼저 노드 크기의 공간을 열고 다음 항목과 NULL을 비어 있음으로 지정한 다음 데이터 필드 값을 x에 할당해야 합니다.

이중 연결 리스트 삽입 및 삭제

  이중 연결 리스트를 삭제하기 위해 가장 먼저 분명히 해야 할 점은 센티넬 비트의 헤드 노드는 전체 이중 연결 리스트의 구조적 지원이기 때문에 삭제할 수 없다는 점입니다. 삭제할 때에는 삭제할 노드의 이전 노드와 다음 노드를 찾아 이전 노드의 다음 포인터가 다음 노드를 가리키고, 다음 노드의 이전 포인터가 이전 노드를 가리킨다. 마지막으로 삭제된 노드 공간이 해제됩니다.

  이중 연결 리스트 삽입 시 이론적으로 어떤 위치에도 노드를 삽입할 수 있습니다. 초기화 시 새로 생성된 노드를 정의하는 포인터 필드가 모두 비어 있기 때문입니다. 따라서 삽입할 때 삽입된 노드의 두 포인터 필드를 변경하고 다음 포인터가 다음 노드를 가리키며 이전 포인터가 이전 노드를 가리키도록 해야 합니다. 마찬가지로 이전 노드의 다음 포인터가 이 새 노드를 가리키고 다음 포인터의 이전 포인터가 이 새 노드를 가리킵니다.

추천

출처blog.csdn.net/zyb___/article/details/132063876