链表(二) 双链表操作详解

news/2024/12/22 10:08:09/

文章目录

  • 四、双向带头循环链表的实现
    • List.h
    • List.c
      • 创建返回链表的头结点
      • 双向链表打印
      • 双向链表尾插
      • 双向链表尾删
      • 双向链表头插
      • 双向链表头删
      • 双向链表查找
      • 双向链表在pos的前面进行插入
      • 双向链表删除pos位置的节点
  • 五、单链表与双链表比较

什么是链表及单链表的实现请跳转: 链表(一) 单链表操作详解
在这里插入图片描述

四、双向带头循环链表的实现

在这里插入图片描述

在这里插入图片描述
代码结构设计:

  • List.h: 存放链表结构及需要用到的头文件,函数声明等
  • List.c: 各种操作函数的具体实现

List.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>// 带头+双向+循环链表增删查改实现typedef int LTDataType;typedef struct ListNode
{LTDataType data;struct ListNode* next;struct ListNode* prev;
}ListNode;// 创建返回链表的头结点.
ListNode* ListCreate();
// 双向链表打印
void ListPrint(ListNode* pHead);
// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x);
// 双向链表尾删
void ListPopBack(ListNode* pHead);
// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x);
// 双向链表头删
void ListPopFront(ListNode* pHead);
// 双向链表查找
ListNode* ListFind(ListNode* pHead, LTDataType x);
// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x);
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos);

List.c

#include "List.h"//创建节点,此函数用于方便创建节点
ListNode* ListBuy(int x)
{ListNode* node = (ListNode*)malloc(sizeof(ListNode));if (node == NULL){perror("malloc fail");exit(-1);}node->data = x;node->next = NULL;node->prev = NULL;return node;
}

创建返回链表的头结点

ListNode* ListCreate()
{ListNode* head = ListBuy(0);head->next = head;head->prev = head;return head;
}

在这里插入图片描述

双向链表打印

void ListPrint(ListNode* pHead)
{assert(pHead);ListNode* cur = pHead->next;printf("head <=> ");while (cur != pHead){printf("%d <=> ", cur->data);cur = cur->next;}printf("\n");
}

双向链表尾插

void ListPushBack(ListNode* pHead, LTDataType x)
{assert(pHead);ListNode* newNode = ListBuy(x);ListNode* tail = pHead->prev;tail->next = newNode;newNode->prev = tail;pHead->prev = newNode;newNode->next = pHead;
}

在这里插入图片描述

双向链表尾删

void ListPopBack(ListNode* pHead)
{assert(pHead);assert(pHead->next!=pHead);ListNode* tail = pHead->prev;ListNode* tailPrev = tail->prev;free(tail);tailPrev->next = pHead;pHead->prev = tailPrev;
}

在这里插入图片描述

双向链表头插

void ListPushFront(ListNode* pHead, LTDataType x)
{assert(pHead);ListNode* first = pHead->next;ListNode* newNode = ListBuy(x);pHead->next = newNode;newNode->prev = pHead;newNode->next = first;first->prev = newNode;
}

在这里插入图片描述

双向链表头删

void ListPopFront(ListNode* pHead)
{assert(pHead);assert(pHead->next!=pHead);ListNode* first = pHead->next;ListNode* second = pHead->next->next;free(first);pHead->next = second;second->prev = pHead;
}

在这里插入图片描述

双向链表查找

ListNode* ListFind(ListNode* pHead, LTDataType x)
{assert(pHead);ListNode* cur = pHead->next;while (cur != pHead){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}

双向链表在pos的前面进行插入

void ListInsert(ListNode* pos, LTDataType x)
{assert(pos);ListNode* posPrev = pos->prev;ListNode* newNode = ListBuy(x);posPrev->next = newNode;newNode->prev = posPrev;newNode->next = pos;pos->prev = newNode;
}

在这里插入图片描述

双向链表删除pos位置的节点

void ListErase(ListNode* pos)
{assert(pos);ListNode* posPrev = pos->prev;ListNode* posNext = pos->next;free(pos);posPrev->next = posNext;posNext->prev = posPrev;
}

在这里插入图片描述

五、单链表与双链表比较

单链表双链表
存储空间物理上一定连续逻辑上连续,物理上不一定
随机访问支持 :O(1)不支持 :O(n)
任意位置插入删除元素可能需要搬移元素,效率低:O(N)只需修改指针指向
插入动态顺序表,空间不够时需要扩容没有容量的概念
应用场景元素高效存储+频繁访问任意位置插入和删除频繁
缓存利用率

http://www.ppmy.cn/news/1001901.html

相关文章

【leetcode】203. 移除链表元素(easy)

给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* Lis…

垃圾回收机制和常用的算法

一.什么是垃圾回收&#xff1f; 垃圾回收主要针对堆和方法区&#xff08;非堆&#xff09;,程序计数器&#xff0c;虚拟机栈&#xff0c;本地方法栈这三个区域属于线程私有&#xff0c;随着线程的销毁&#xff0c;自然就会雄安会了&#xff0c;因此不需要堆着三个区域进行垃圾…

【UE5】UE5与Python Socket通信中文数据接收不全

最近在使用UE的Socket模块与Python服务器进行通信时遇到了一些坑&#xff0c;特此记录一下。 先来复现一下问题&#xff0c;这里只截取关键代码。 UE端&#xff1a; bool ASoc::SendMsg(const FString& Msg) {TSharedRef<FInternetAddr> TargetAddr ISocketSubsy…

【NLP概念源和流】 04-过度到RNN(第 4/20 部分)

接上文 【NLP概念源和流】 03-基于计数的嵌入,GloVe(第 3/20 部分) 一、说明 词嵌入使许多NLP任务有了显著的改进。它对单词原理图的理解以及将不同长度的文本表示为固定向量的能力使其在许多复杂的NLP任务中非常受欢迎。大多数机器学习算法可以直接应用于分类和回归任务的…

iframe跨域解决方案

在 Web 开发中&#xff0c;跨域是指在一个域&#xff08;例如&#xff0c;https://www.example.com&#xff09;的页面中请求了另一个域&#xff08;例如&#xff0c;https://api.example.com&#xff09;的资源&#xff0c;浏览器出于安全考虑会阻止这样的请求。为了解决 ifra…

4-百度地图

4-百度地图 一 百度地图 1 前期准备 H5端和PC端,对接百度提供JavaScript API。 移动端,对接百度android SDK或ios SDK (1)打开百度地图开放平台 地址:https://lbsyun.baidu.com/ (2)选中开发文档——JavaScript Api 按照文档步骤开通百度开放平台并申请密钥 2 展示地…

以技术驱动反欺诈,Riskified 为企业出海保驾护航

如今&#xff0c;全球对于线上消费的需求日益增长&#xff0c;各类新型支付方式也层出不穷。在国内&#xff0c;线上支付有着较为完善的法律及监管条例&#xff0c;格局基本已定型。但对于出海商家而言&#xff0c;由于不同国家和地区的支付规则和监管机制不同&#xff0c;跨境…

【多线程系列-04】深入理解java中线程间的通信机制

多线程系列整体栏目 内容链接地址【一】深入理解进程、线程和CPU之间的关系https://blog.csdn.net/zhenghuishengq/article/details/131714191【二】java创建线程的方式到底有几种&#xff1f;(详解)https://blog.csdn.net/zhenghuishengq/article/details/127968166【三】深入…