数据结构和算法学习记录——线性表之双向链表(上)-结点类型定义、初始化函数、创建新结点函数、尾插函数、打印函数、尾删函数

简介: 数据结构和算法学习记录——线性表之双向链表(上)-结点类型定义、初始化函数、创建新结点函数、尾插函数、打印函数、尾删函数

结点类型定义

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
 
typedef int LTDataType;
 
typedef struct ListNode
{
    LTDataType data;
    struct ListNode* next;
    struct ListNode* prev;
}LTNode;

初始化函数

LTNode* ListInit()
{
    //哨兵位头结点
    LTNode* phead = (LTNode*)malloc(sizeof(LTNode));
    phead->next = NULL;
    phead->prev = NULL;
 
    return phead;
}

创建新结点函数

LTNode* BuyListNode(LTDataType x)
{
    LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
    newnode->data = x;
    newnode->next = NULL;
    newnode->prev = NULL;
    return newnode;
}

尾插函数

代码

void ListPushBack(LTNode* phead, LTDataType x)
{
    assert(phead);
 
    LTNode* newnode = BuyListNode(x);
    LTNode* tail = phead->prev;
 
    tail->next = newnode;
    newnode->prev = tail;
    newnode->next = phead;
    phead->prev = newnode;
}

实现思路

为什么这个尾插函数不需要传入二级指针呢?

详细看我们的代码:


我们至始至终,有改变其值的,只有tail中的next指针、newnode的prev指针、newnode的next指针和phead的prev指针。

而phead本身的地址,或者说phead本身的值并没有被改变,所以就不需要传入二级指针来改变phead的值了。

打印双向链表函数

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

尾删函数

实现方式一

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

实现方式二

void ListPopBack(LTNode* phead)
{
    assert(phead);
    assert(phead->next != phead);
    LTNode* tail = phead->prev;
 
    phead->prev = tail->prev;
    tail->prev->next = phead;
    free(tail);
}


第二种赋值的语句先后顺序无影响

需要注意的是:不能把哨兵位结点也一起删了,即当phead->next == phead时,就表示此事链表为空,只剩下一个哨兵位结点了。该结点不存数据。


线性表之双向链表(下)

目录
相关文章
|
3月前
|
存储 Java
数据结构第二篇【关于java线性表(顺序表)的基本操作】
数据结构第二篇【关于java线性表(顺序表)的基本操作】
49 6
【数据结构】——双向链表详细理解和实现
【数据结构】——双向链表详细理解和实现
|
2月前
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习之王道第2.3章节之线性表精题汇总二(5)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
IKU达人之数据结构与算法系列学习×单双链表精题详解、数据结构、C++、排序算法、java 、动态规划 你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
3月前
|
人工智能 算法 前端开发
无界批发零售定义及无界AI算法,打破传统壁垒,累积数据流量
“无界批发与零售”是一种结合了批发与零售的商业模式,通过后端逻辑、数据库设计和前端用户界面实现。该模式支持用户注册、登录、商品管理、订单处理、批发与零售功能,并根据用户行为计算信用等级,确保交易安全与高效。
|
3月前
|
存储
探索数据结构:便捷的双向链表
探索数据结构:便捷的双向链表
|
3月前
01(数据结构考研)线性表相关操作代码
01(数据结构考研)线性表相关操作代码
90 0
|
2月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
241 9
|
2月前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
40 1
|
2月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
71 5
|
2月前
|
存储 算法 Java
数据结构的栈
栈作为一种简单而高效的数据结构,在计算机科学和软件开发中有着广泛的应用。通过合理地使用栈,可以有效地解决许多与数据存储和操作相关的问题。