《算法导论》学习笔记之Chapter10---数据结构之链表

2024-05-16 00:18

本文主要是介绍《算法导论》学习笔记之Chapter10---数据结构之链表,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

链表定义:链表是这样一种数据结构,其中的各对象按线性顺序排列,与数组的线性顺序由下标决定不同,链表的顺序是由各个对象里的指针决定。

链表分为:单向链表,双向链表,还有循环链表。

链表支持的操作有:查找Search;插入Insert;删除Delete;

双向链表的查找操作就是从表头开始对比查找,很简单;插入操作,是根据插入的数据的指针属性来寻找要插入的位置;之后修改相关元素的pre和next指针属性即可;删除操作与插入操作类似,只是在找到要删除的元素的位置之后,直接将该元素前一个节点的next属性设置为被删除节点的next属性值,将被删除节点后面的节点的pre属性值设置为被删除节点的pre属性值即可。可以自行画图来加深理解。而在链表中,有一个重要的定义就是-节点,前面所说的元素值,pre,next属性都应该包含在节点里面的。

注意,链表的查找,删除操作其实都是可以分为按照内容的操作和按照指针的操作的。

本文,介绍单向链表和双向链表的几种java实现。

下面是单向链表的基本操作的代码实现:

import java.util.List;public class LinkedListTest {Node head = null;// 链表头/*** 向链表中插入数据* * @param args*/public void insert(int d) {Node newNode = new Node(d);// 将要插入的数据包装成链表的节点// 如果链表为空,则将要插入节点作为头节点if (head == null) {head = newNode;return;}// 下面代码是寻找链表的尾节点Node tmp = head;while (tmp.next != null) {tmp = tmp.next;}// 将新节点插入大奥为节点的后面tmp.next = newNode;}// 删除第i个节点public boolean deletaNode(int i) {// 如果删除的位置不合理,则返回falseif (i < 1 && i > length()) {return false;}// 删除的是链表的头结点if (i == 1) {head = head.next;return true;}// 删除的是链表的中间节点int j = 2;Node preNode = head;Node curNode = preNode.next;while (curNode != null) {if (j == i) {preNode.next = curNode.next;return true;}preNode = curNode;curNode = curNode.next;j++;}return true;}// 返回链表的长度public int length() {int length = 0;Node tmp = head;while (tmp != null) {tmp = tmp.next;length++;}return length;}// 链表排序,返回排序后的头节点public Node sortList() {Node nextNode = null;int tmp = 0;Node curNode = head;// 采用冒泡排序的方法对链表数据进行排序while (curNode.next != null) {nextNode = curNode.next;while (nextNode != null) {if (curNode.data > nextNode.data) {tmp = curNode.data;curNode.data = nextNode.data;nextNode.data = tmp;}nextNode = nextNode.next;}curNode = curNode.next;}return head;}// 打印链表public void printList() {Node tmp = head;while (tmp != null) {System.out.println(tmp.data);tmp = tmp.next;}}public static void main(String[] args) {// TODO Auto-generated method stubLinkedListTest list = new LinkedListTest();list.insert(5);list.insert(1);list.insert(4);list.insert(3);list.insert(2);System.out.println(list.length());list.printList();list.sortList();list.printList();list.deletaNode(1);list.printList();list.deletaNode(3);list.printList();}}// 定义链表的节点类型
class Node {int data;Node next = null;public Node(int data) {this.data = data;}
}

下面介绍单链表中的删除重复数据的方法:

/*** 删除重复数据 方法1时间复杂度小,但是需要额外的存储空间 方法2时间复杂度高,但是不需要额外的存储空间* * @param head*/public void deleteDuplecate1(Node head) {Hashtable<Integer, Integer> table = new Hashtable<Integer, Integer>();Node tmp = head;Node pre = null;while (tmp != null) {if (table.containsKey(tmp.data)) {pre.next = tmp.next;} else {table.put(tmp.data, 1);pre = tmp;}tmp = tmp.next;}}public void deleteDuplecate2(Node head) {Node tmp = head;while (tmp != null) {Node cur = head;Node pre = null;while (cur != tmp) {if (cur.data == tmp.data) {pre.next = cur.next;break;} else {pre = cur;cur = cur.next;}}tmp = tmp.next;}tmp = tmp.next;}

寻找链表中倒数第k个节点:

//如何找到链表中倒数第k个节点,重点在倒数public Node find(Node head, int k){if( k < 1 || k > this.length()){return null;}Node p1 = head;Node p2 = head;//将p1指针向后先移动k个位置,这样当P1移动到结尾时,p2的位置就是倒数第kfor(int i = 0; i < k - 1; i++){p1 = p1.next;}while(p1 != null){p1 = p1.next;p2 = p2.next;}return p2;}

实现链表的反转(非递归实现):

// 链表反转非递归实现public void reverse(Node head) {Node pRevereHead = head;Node pNode = head;Node pPre = null;while (pNode != null) {// pNext用来记录下一个节点,防止pNode的next节点转向之后,与后面的节点断开联系Node pNext = pNode.next;if (pNext == null) {pRevereHead = pNode;}pNode.next = pPre;pPre = pNode;pNode = pNext;}this.head = pRevereHead;}

下面还有关于单向链表的好几种操作,在此我就只记录一下这几个操作的思想吧:

从链表尾部开始输出节点:使用递归,每访问到一个节点,先递归输出后面的节点,再输出该节点自身。

访问链表中间节点:是用两个指针,一个指针单步移动,一个指针双步移动,当双步指针移动到链表尾部,则单步指针指向的节点为链表中间节点。

如何判断两个链表是否相交:如果链表相交,则一定有相同的尾节点。



这篇关于《算法导论》学习笔记之Chapter10---数据结构之链表的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

Go语言中三种容器类型的数据结构详解

《Go语言中三种容器类型的数据结构详解》在Go语言中,有三种主要的容器类型用于存储和操作集合数据:本文主要介绍三者的使用与区别,感兴趣的小伙伴可以跟随小编一起学习一下... 目录基本概念1. 数组(Array)2. 切片(Slice)3. 映射(Map)对比总结注意事项基本概念在 Go 语言中,有三种主要

Python中的随机森林算法与实战

《Python中的随机森林算法与实战》本文详细介绍了随机森林算法,包括其原理、实现步骤、分类和回归案例,并讨论了其优点和缺点,通过面向对象编程实现了一个简单的随机森林模型,并应用于鸢尾花分类和波士顿房... 目录1、随机森林算法概述2、随机森林的原理3、实现步骤4、分类案例:使用随机森林预测鸢尾花品种4.1

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第