目录
一、前言
今天讲一下最实用的双链表,这个比单链表更厉害了,下图中,头尾节点的增删都为O(1),虽结构复杂一点,但是效率更高
时间复杂度好坏可以参考前面所写的数据结构进行比较
🔗 🔗 🔗 顺序表 🔗 🔗 🔗
👉 👉 👉 单链表 👈 👈 👈
二、整体框架设计
还是和之前一样实现doubleLinkList分为三个文件,这样可读性更高,便于调试
test.c 专门用于函数调用、调试
doubleList.h 只用于函数声明
doubleList.c 用于函数实现
三、函数实现
在实现函数之前,我们想一想双链表需要怎样设计呢?如果按照单链表的思想去设计,那么尾插要达到O(1)是根本做不到的,除非头节点可以直接去访问尾节点,但单链表中当前节点要访问前一个节点的话,不做记录是根本不可能访问到的呀
那怎么办呢?
有人肯定想到了在结构体中添加一个新的成员,创建一个pre指针用于存储当前节点的前一个节点的地址不就可以了嘛
那么问题又来了,头节点怎么就能直接访问到尾节点了呢?
带着这个疑惑我们参考一下上图,发现head节点的前一个节点是指向最后一个节点的,那么也就实现了一步到位
我们先来看下头文件的构
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
typedef int DataType;
typedef struct doubleLinkList{
DataType data;
struct doubleLinkList* pre;
struct doubleLinkList* next;
}DBLST;
DataType的定义是为了方便修改数据类型,这样定义一下,下次变char类型就实现了全局修改,awesome~
结构体中有三个成员分别用于数据存储,当前节点的前一个节点地址记录和当前节点的下一个节点的地址记录。
1. createDBLSTNode
首先最基本的函数就是专用于新节点创建,因为这个函数后续需要频繁使用
DBLST* createDBLSTNode(DataType x){
DBLST* newNode = (DBLST*)malloc(sizeof(DBLST));
if(newNode == NULL){
printf("Failed to create a new node");
exit(-1);
}
newNode->pre = NULL;
newNode->next = NULL;
newNode->data = x;
return newNode;
}
2. doubleListInit
这个初始化和前面的顺序表,单链表不太一样
我们先创建一个节点,将新节点的地址传给原来的head,然后将此节点的pre和next都指向自己,就完成了双链表的创建
void doubleListInit(DBLST** head){
*head = createDBLSTNode(-1);
(*head)->pre = *head;
(*head)->next =