数据结构-线性表之带头结点的双向循环链表

前言

链表的类型有很多种(根据带头或不带头,循环或非循环等等),但是我们重点研究的只有两种,一种结构非常简单是无头单向非循环链表,有关它的操作见

数据结构-线性表之单链表

这种结果在开发中基本不会使用,因为因为结构简单往往意味着操作复杂,比如在求职中OJ题,有关链表的基本都用的是这种结构,关于这些OJ题感兴趣的见

链表经典题

另一种则是链表中结构最为复杂的——带头结点的双向循环链表
在这里插入图片描述
这种结构看起来确实是很复杂的,但是它的操作很简单,比如最常用的尾插操作,其时间复杂度为O(1)。同时C++中STL中的list就是这种结构
对于这种结构,由于它的带了头结点,所以能使大部分操作使用相同代码实现,如头插等等,又因为它是循环的,所以方便了尾插等操作

注意其链表的空的判断情况

head->prev=head
haed->next=head

实现

(1)结构定义

typedef struct DListNode
{
    
    
	struct ListNode* next;//指向前一个结点
	struct ListNode* prev;//指向后一个结点
	DLdatatype val;
}DListNode;

(2)基本函数

1:申请结点
在这里插入图片描述
2:打印
对于打印稍加注意,在这种结构中是没有NULL的,也就是判断结束的条件不能去找NULL,而是要找头
在这里插入图片描述

(3)操作实现

1:尾插
在这里插入图片描述
在这里插入图片描述
2:尾删
在这里插入图片描述
在这里插入图片描述
3:头插
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
4:头删
在这里插入图片描述
5:找结点

在这里插入图片描述
6:任意位置插入(某节点之后)
在这里插入图片描述
7:在任意位置插入(某节点之前)
在这里插入图片描述
8:任意位置删除
在这里插入图片描述
9:销毁
在这里插入图片描述

测试

在这里插入图片描述

代码

Dlist.h

#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

typedef int DLdatatype;
typedef struct DListNode
{
    
    
	struct DListNode* next;
	struct DListNode* prev;
	DLdatatype val;

}DListNode;

void printlist(DListNode* head);//打印
DListNode* CreatNode(DLdatatype x);//申请结点

void ListPushBack(DListNode* head, DLdatatype x);//尾插
void ListPopBack(DListNode* head);//尾删
void listPushFront(DListNode* head, DLdatatype x);//头插
void listPopFront(DListNode* head);//头删

DListNode* find(DListNode* head, DLdatatype x);//找某个元素
void listinseret_behind(DListNode* head,DLdatatype pos, DLdatatype x);//任意位置插入(后面)
void listinseret_front(DListNode* head,DLdatatype pos, DLdatatype x);//任意位置插入(前面)
void listdelete(DListNode* head,DLdatatype pos);//任意位置删除

void listdestory(DListNode* head);//链表销毁

Dlist.c

#include "DList.h"

DListNode* CreatNode(DLdatatype x)
{
    
    
	DListNode* NewNode = (DListNode*)malloc(sizeof(DListNode));
	NewNode->val = x;
	NewNode->next = NULL;
	NewNode->prev = NULL;
	return NewNode;
}

void printlist(DListNode* head)
{
    
    
	assert(head);
	DListNode* cur = head->next;
	while (cur!=head)
	{
    
    
		printf("%d->", cur->val);
		cur = cur->next;
	}
	if (head->next == head)
		printf("NULL");

}

void ListPushBack(DListNode* head, DLdatatype x)
{
    
    
	assert(head);
	DListNode* NewNode=CreatNode(x);

	NewNode->next = head;
	(head->prev)->next = NewNode;
	NewNode->prev = head->prev;
	head->prev = NewNode;
}

void ListPopBack(DListNode* head)
{
    
    
	assert(head);
	assert(head->next != head);//如果链表为空,断言
	DListNode* delelte = head->prev;
	head->prev = delelte->prev;
	delelte->prev->next = head;
	free(delelte);
}

void listPushFront(DListNode* head, DLdatatype x)
{
    
    
	assert(head);
	DListNode* NewNode = CreatNode(x);

	NewNode->next = head->next;
	NewNode->prev = head;
	head->next->prev = NewNode;
	head->next = NewNode;

}
void listPopFront(DListNode* head)
{
    
    
	assert(head);
	assert(head->next != head);
	DListNode* first = head->next;
	first->next->prev = head;
	head->next = first->next;
	free(first);

}

DListNode* find(DListNode* head, DLdatatype x)
{
    
    
	assert(head);
	DListNode* cur = head->next;
	while (cur->next != head && cur->val != x)
	{
    
    
		cur = cur->next;
	}
	if (cur->next == head && cur->val!=x)
	{
    
    
		return NULL;//未找到
	}
	else
	{
    
    
		return cur;//否则返回
	}

}

void listinseret_behind(DListNode* head, DLdatatype pos, DLdatatype x)
{
    
    
	assert(head);
	DListNode* insert = find(head, pos);
	if (insert == NULL)
	{
    
    
		printf("%d不存在\n", pos);
	}
	else
	{
    
    
		DListNode* NewNode = CreatNode(x);
		NewNode->next = insert->next;
		NewNode->prev = insert;
		insert->next->prev = NewNode;
		insert->next = NewNode;
	}

}

void listinseret_front(DListNode* head, DLdatatype pos, DLdatatype x)
{
    
    
	assert(head);
	DListNode* insert = find(head, pos);
	if (insert == NULL)
	{
    
    
		printf("%d不存在\n", pos);
	}
	
	{
    
    
		DListNode* NewNode = CreatNode(x);
		NewNode->next = insert;
		NewNode->prev = insert->prev;
		NewNode->prev->next = NewNode;
		insert->prev = NewNode;
	
	}

}

void listdelete(DListNode* head, DLdatatype pos)
{
    
    
	assert(head);
	assert(pos != head);
	DListNode* delete = find(head, pos);
	if (delete == NULL)
	{
    
    
		printf("%d不存在\n", pos);
	}
	else
	{
    
    
		delete->prev->next = delete->next;
		delete->next->prev = delete->prev;
		free(delete);
	}

}

void listdestory(DListNode* head)
{
    
    
	assert(head);
	DListNode* cur = head->next;
	DListNode* pre = NULL;
	while (cur->next != head)
	{
    
    
		pre = cur;
		cur = cur->next;
		free(pre);
		
	}
	head->next =head;
	head->prev = head;

}

test.c

#include "DList.h"

void test()
{
    
    
	DListNode* head=(DListNode*)malloc(sizeof(DListNode));
	head->prev = head;
	head->next = head;
	printf("尾插4个结点\n");
	ListPushBack(head, 1);
	ListPushBack(head, 2);
	ListPushBack(head, 3);
	ListPushBack(head, 4);
	printlist(head);
	printf("\n");
	printf("\n");

	printf("尾删2个结点\n");
	ListPopBack(head);
	ListPopBack(head);
	printlist(head);
	printf("\n");
	printf("\n");

	printf("头插4个结点\n");
	listPushFront(head, 5);
	listPushFront(head, 6);
	listPushFront(head, 7);
	listPushFront(head, 8);
	printlist(head);
	printf("\n");
	printf("\n");

	printf("头删2个结点\n");
	listPopFront(head);
	listPopFront(head);
	printlist(head);
	printf("\n");
	printf("\n");

	printf("在5后面插入7\n");
	listinseret_behind(head, 5, 7);
	printlist(head);
	printf("\n");
	printf("\n");

	printf("删除1\n");
	listdelete(head, 1);
	printlist(head);
	printf("\n");
	printf("\n");


	printf("销毁\n");
	listdestory(head);
	printlist(head);
	printf("\n");
	printf("\n");

}

int main()
{
    
    
	test();
}

猜你喜欢

转载自blog.csdn.net/qq_39183034/article/details/113136845