单向链表与双向链表

2024-09-04 23:20
文章标签 链表 双向 单向

本文主要是介绍单向链表与双向链表,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

当使用单向链表查看链表中某个节点的数据,可以使用快慢指针法

快慢指针:

快慢指针是一种在链表和数组中常用的算法技巧,主要用于解决链表或数组中的问题,如检测环

存在、找到环的入口、计算链表的中点等。快慢指针的核心思想是使用两个指针以不同的速度遍

链表或数组:

>慢指针(Slow Pointer):每次移动一步。

>快指针(Fast Pointer):每次移动两步。

使用场景

检测链表是否有环
  1. 如果快指针最终追上慢指针,说明链表中有环。

  2. 如果快指针到达链表的末尾,说明链表中没有环。

bool HasCircle(Node *head)
{if(head == NULL)return false;Node *slow = head, *fast = head;while(fast != NULL && fast->next!=NULL){slow = slow->next; //慢指针每次前进一步fast = fast->next->next;//快指针每次前进两步if(slow == fast) //相遇,存在环return true;}return false;
}
输出链表中的倒数第K个节点(即正数第K-1个节点)
Link_node_t * find_k_link(Link_t *plink,int key)
{Link_node_t *pfast = find_link(plink,key);if(NULL == pfast){return NULL;}pfast = pfast->pnext;Link_node_t *pslow = plink->phead;while(pfast != NULL){pfast = pfast->pnext;pslow = pslow->pnext;}return pslow;
}

单向链表倒置

int inver_link(Link_t *plink)
{int len = link_lenth(plink);if(len == 0){return -1;}Link_node_t *ptemp = plink->phead;plink->phead = NULL;Link_node_t *pinsert = NULL;while(ptemp != NULL){pinsert = ptemp;ptemp = ptemp->pnext;pinsert->pnext = plink->phead;plink->phead = pinsert;}return 0;
}

单向链表排序(插入法)

将待插入的数,插入到一个有序的序列中,使得到的序列仍然有序

void insert_sort(Link_t *plink)
{Link_node_t *ptemp = plink->phead->pnext;plink->phead->pnext = NULL;while(ptemp != NULL){Link_node_t *pinsert = ptemp;ptemp = ptemp->pnext;Link_node_t *p = NULL;if(plink->phead->data > pinsert->data){pinsert->pnext = plink->phead;plink->phead = pinsert;}else{p = plink->phead;while(p->pnext != NULL && p->pnext->data < pinsert->data){p = p->pnext;}pinsert->pnext = p->pnext;p->pnext = pinsert;}}
}

valgrind

在使用和操作链表时,需注意内存泄漏的情况,可以使用Valgrind来检查内存泄漏的情况

Valgrind 是一个编程工具,主要用于内存调试、内存泄漏检测、以及性能分析。

使用场景

>内存泄漏检测:检查程序是否在不再需要时未能释放分配的内存。

>内存越界:检测数组越界、堆栈缓冲区溢出等错误。

>线程错误:检查多线程程序中的同步问题,如死锁、竞争条件等。

>性能分析:分析程序的性能瓶颈,如CPU周期使用、内存访问模式等。

安装valgrind

sudo apt-get update
sudo apt-get install valgrind

运行valgrind

valgrind [选项] 程序名 [程序参数]

使用示例:


双向链表

双向链表与单向链表的区别:

单向链表只有一个后继指针

对于单向链表的某一个节点,只能找到其后的节点,而不能找到之前的节点

基础操作

头插
int push_doulink_head(Dlink_t *plink,DataType data)
{Dlink_node_t *pdouble = malloc(sizeof(Dlink_node_t));if(NULL == pdouble){return -1;}pdouble->data = data;pdouble->pnext = NULL;pdouble->ppre = NULL;if(is_empty_link(plink)){plink->phead = pdouble;}else{pdouble->pnext = plink->phead;plink->phead->ppre = pdouble;plink->phead = pdouble;}plink->clen++;return 0;
}
尾插
int push_doulink_end(Dlink_t *plink,DataType data)
{Dlink_node_t *pnode = malloc(sizeof(Dlink_node_t));if(NULL == pnode){return -1;}pnode->data = data;pnode->ppre = NULL;pnode->pnext = NULL;if(is_empty_link(plink)){push_doulink_head(plink,data);}else{Dlink_node_t *p = plink->phead;while(p->pnext != NULL){p = p->pnext;}p->pnext = pnode;pnode->ppre = p;}plink->clen++;return 0;
}
头删
int pop_link_head(Dlink_t *plink)
{Dlink_node_t *pnode = plink->phead;if(plink->phead ==NULL){return 0;}else{Dlink_node_t *pdel = pnode;plink->phead = pnode->pnext;pnode->pnext->ppre = NULL;free(pdel);}plink->clen--;return 0;
}
尾删
int pop_link_end(Dlink_t *plink)
{Dlink_node_t *pnode = plink->phead;if(plink->phead == NULL){return 0;}else if(pnode->pnext == NULL){pop_link_head(plink);}else{while(pnode->pnext->pnext != NULL){pnode = pnode->pnext;}pnode->pnext = NULL;free(pnode->pnext);}return 0;
}

这篇关于单向链表与双向链表的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1137324

相关文章

csu1329(双向链表)

题意:给n个盒子,编号为1到n,四个操作:1、将x盒子移到y的左边;2、将x盒子移到y的右边;3、交换x和y盒子的位置;4、将所有的盒子反过来放。 思路分析:用双向链表解决。每个操作的时间复杂度为O(1),用数组来模拟链表,下面的代码是参考刘老师的标程写的。 代码如下: #include<iostream>#include<algorithm>#include<stdio.h>#

深入手撕链表

链表 分类概念单链表增尾插头插插入 删尾删头删删除 查完整实现带头不带头 双向链表初始化增尾插头插插入 删查完整代码 数组 分类 #mermaid-svg-qKD178fTiiaYeKjl {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-

建立升序链表

题目1181:遍历链表 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2744 解决:1186 题目描述: 建立一个升序链表并遍历输出。 输入: 输入的每个案例中第一行包括1个整数:n(1<=n<=1000),接下来的一行包括n个整数。 输出: 可能有多组测试数据,对于每组数据, 将n个整数建立升序链表,之后遍历链表并输出。 样例输

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟)

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟) 题目描述 给定一个链表,链表中的每个节点代表一个整数。链表中的整数由 0 分隔开,表示不同的区间。链表的开始和结束节点的值都为 0。任务是将每两个相邻的 0 之间的所有节点合并成一个节点,新节点的值为原区间内所有节点值的和。合并后,需要移除所有的 0,并返回修改后的链表头节点。 思路分析 初始化:创建一个虚拟头节点

学习记录:js算法(二十八):删除排序链表中的重复元素、删除排序链表中的重复元素II

文章目录 删除排序链表中的重复元素我的思路解法一:循环解法二:递归 网上思路 删除排序链表中的重复元素 II我的思路网上思路 总结 删除排序链表中的重复元素 给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。 图一 图二 示例 1:(图一)输入:head = [1,1,2]输出:[1,2]示例 2:(图

react笔记 8-19 事件对象、获取dom元素、双向绑定

1、事件对象event 通过事件的event对象获取它的dom元素 run=(event)=>{event.target.style="background:yellowgreen" //event的父级为他本身event.target.getAttribute("aid") //这样便获取到了它的自定义属性aid}render() {return (<div><h2>{

【数据结构与算法 | 灵神题单 | 删除链表篇】力扣3217, 82, 237

总结,删除链表节点问题使用到列表,哈希表,递归比较容易超时,我觉得使用计数排序比较稳,处理起来也不是很难。 1. 力扣3217:从链表中移除在数组中的节点 1.1 题目: 给你一个整数数组 nums 和一个链表的头节点 head。从链表中移除所有存在于 nums 中的节点后,返回修改后的链表的头节点。 示例 1: 输入: nums = [1,2,3], head = [1,2,3,

c++ 链表详细介绍

链表是数据结构的一种,由节点组成,每个节点包含数据和指向下一个节点的指针。链表在C++中的实现可以是单链表、双链表或循环链表。以下是链表的详细介绍: 1. 单链表 结构: 节点(Node):每个节点包含数据和一个指针(next),指向链表中的下一个节点。 示例结构: struct Node {int data;Node* next;Node(int d) : data(d), next(

带头结点的线性链表的基本操作

持续了好久,终于有了这篇博客,链表的操作需要借助图像模型进行反复学习,这里尽可能的整理并记录下自己的思考,以备后面复习,和大家分享。需要说明的是,我们从实际应用角度出发重新定义了线性表。 一. 定义 从上一篇文章可以看到,由于链表在空间的合理利用上和插入、删除时不需要移动等优点,因此在很多场合下,它是线性表的首选存储结构。然而,它也存在某些实现的缺点,如求线性表的长度时不如顺序存储结构的

数据结构基础(栈,队列,数组,链表,树)

栈:后进先出,先进后出 队列:先进先出,后进后出 数组:查询速度快,通过地址值和索引定位,查询任意数据消耗时长相同,在内存中是连续存储的,删除效率低,要将原始数据删除,然后后面的数据前移,添加效率低,添加索引位置的元素,剩下的都需要向前后移动 链表:节点的存储位置(地址)里面存储本身的数据值,和下一个节点的地址值,链表中的节点是独立对象,在内存中是不连续的。查询速度慢,无论查询哪个数据都要从