链表

java数据结构----链表

試著忘記壹切 提交于 2020-02-06 15:52:37
一.概述 1.概念 链表: 链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针连接次序实现的。每一个链表都包含多个节点,节点又包含两个部分,一个是数据域(储存节点含有的信息),一个是引用域(储存下一个节点或者上一个节点的地址)。 2.使用链表的优缺点 使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。 3.链表分类 链表分为 单向链表和双向链表 二. 单向链表 1.单向链表概述 单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点由元素和指针构成。在Java中,我们 可以将单链表定义成一个类,单链表的基本操作即是类的方法,而结点就是一个个实例化的对象,每个对象中都有“元素值”和“下一结点地址”两个属性。在“下一结点地址”属性中存储的是下一个对象的引用,这样,一个个对象连在一起就成为了单链表。 2.单链表的逻辑结构 单链表是链表中结构最简单的。一个单链表的节点(Node)分为两个部分,第一个部分(data)保存或者显示关于节点的信息,另一个部分存储下一个节点的地址。最后一个节点存储地址的部分指向空值。 3.单链表的实现(水浒英雄排名案例)

2017-2018-2 《程序设计与数据结构》第11周学习总结

混江龙づ霸主 提交于 2020-02-06 14:07:14
20172312 2017-2018-2 《程序设计与数据结构》第10周学习总结 教材学习内容总结 本周的十三章其实不是很难(或者说我个人认为不是很难),感觉本周的难点更偏向于实验,尤其是第三,四项实验的难度,相当之大。 本周内容: 对象具有良好定义的接口,这是一种实现集合的机制。 动态数据结构的大小规模可以随需要而改变。 通过存储更改对象引用来实现一个链表管理。 通过仔细操作对象引用,实现插入和删除操作。 队列是一种先进先出的线性数据结构,堆栈则是后进后出。 教材学习中的问题和解决过程 问题1:在数据结构的动态结构当中,对于动态结构的大小规模变化不是很了解。 问题1解决方案: https://blog.csdn.net/fengfeng2861285642/article/details/52304083 链表从本质上讲可以理解为“动态的对象数组”。链表可以实现对象的增加、删除、查询等等一系列的操作,可以实现动态扩充。如下为链表的实现: 代码调试中的问题和解决过程 本周的代码没有遇到太大的问题,基本上就是些大小写错误,以及编码不规范。(话说那个代码规范能删了不,每次都提醒我起名不对。) 代码托管 上周考试错题总结 1.穿越迷宫递归比迭代要容易得多。false A.递归是吸引人的一个原因是它自动回溯到最后一个决定的要点。在穿越迷宫时,当到达死胡同时

[数据结构与算法]第4章 链表

谁说我不能喝 提交于 2020-02-06 12:40:34
个人博客文章地址 文章目录 4.1 单向环形链表应用场景 4.1.1 Josephu(约瑟夫、约瑟夫环) 问题 4.1 单向环形链表应用场景 4.1.1 Josephu(约瑟夫、约瑟夫环) 问题 Josephu 问题为:设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。 提示:用一个不带头结点的循环链表来处理Josephu 问题:先构成一个有n个结点的单循环链表,然后由k结点起从1开始计数,计到m时,对应结点从链表中删除,然后再从被删除结点的下一个结点又从1开始计数,直到最后一个结点从链表中删除算法结束。 约瑟夫问题-创建环形链表的思路图解 约瑟夫问题-小孩出圈的思路分析图 代码实现: public class Josepfu { public static void main ( String [ ] args ) { // 测试一把看看构建环形链表,和遍历是否ok CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList ( ) ; circleSingleLinkedList . addBoy ( 125 ) ; //

学生管理系统(**C语言“链表**”)

落花浮王杯 提交于 2020-02-06 11:50:30
学生管理系统( C语言“链表 ”)@[TOC](这 显示页面 功能设计 主函数 链表 显示界面 void menu ( ) { printf ( "--------------[学生信息管理系统]----------------\n" ) ; printf ( "\t\t1.录入信息\n" ) ; printf ( "\t\t2.浏览信息\n" ) ; printf ( "\t\t3.修改信息\n" ) ; printf ( "\t\t4.删除信息\n" ) ; printf ( "\t\t5.查找信息\n" ) ; printf ( "\t\t6.退出系统\n" ) ; printf ( "-------------------------------------------------\n" ) ; } 功能设计 void keyDown ( ) { int choice = 0 ; struct student data ; struct Node * pMove = NULL ; scanf ( "%d" , & choice ) ; switch ( choice ) { case 1 : printf ( "--------------[录入信息]----------------\n" ) ; printf ( "请输入学生姓名,年龄,性别,电话:" ) ;

leetcode -- 23 mark

梦想的初衷 提交于 2020-02-06 11:22:11
文章目录 23.合并k个有序链表(hard) 题目描述 解题方法 23.合并k个有序链表(hard) 应该属于hard里面的easy题吧 题目描述 合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。 示例: 输入: [ 1->4->5, 1->3->4, 2->6 ] 输出: 1->1->2->3->4->4->5->6 解题方法 每次合并两个,代码如下: struct ListNode * MergeTwoLists(struct ListNode * l1, struct ListNode * l2) { struct ListNode * p, *q; // 分别指向l1,l2 struct ListNode * tail; // 指向新链表表尾 struct ListNode * Head = (struct ListNode *)malloc(sizeof(struct ListNode)); p = l1; q = l2; tail = Head; while (p != NULL && q != NULL) { if (p->val <= q->val) { tail->next = p; p = p->next; } else { tail->next = q; q = q->next; } tail = tail->next; } if (p

从数组到链表2

拜拜、爱过 提交于 2020-02-06 10:51:29
从数组到链表2 理想的情况是,用户可以不确定地添加数据(或者不断添加数据直到用完内存量),而不是先指定要输入多少项,也不用程序分配多余的空间。这可以通过在输入每一项后调用malloc()分配正好能储存该项的空间。如果用户输入3部影片,程序就调用malloc()3次;如果用户输入300部影片,程序就调用malloc()300次。 不过我们又制造了一个麻烦。比较一下一种方法是调用malloc()一次,为300个filem结构请求分配足够的空间;另一种方法是调用malloc()300次,分别为每个file结构请求分配足够的空间。前者分配的是连续的内存块,只需要一个单独的指向struct变量的指针,该指针指向已分配块中的第一个结构。简单的数组表示法让指针访问块中的每个结构,如前面代码段所示。第二种方法的问题是,无法保证每次调用malloc()都能分配到连续的内存块。这意味着结构不一定被连续储存。如图1,因此,与第一种方法储存一个指向300个结构块的指针相比,你需要储存300个指针,每个指针指向一个单独存储的结构。 一种解决方法是创建一个大型的指针数组,并在分配新结构时逐个给这些指针赋值,但是我们不打算使用这种方法: # define TSIZE 45 //储存片名的数组大小 # define FMAX 500 //影片的最大数量 struct film { char title [

删除倒数第n个链表的值

强颜欢笑 提交于 2020-02-06 08:56:53
遍历法, struct Node { int val; struct Node *next; }; void deleteNode(struct Node *temp, int n) { struct Node *start = temp; int len = 1; if (temp == null) return; while (start != null) { start = start->next; len++; } if (len < n) { printf("error"); return; } start = temp; struct Node *temp1 = start; if (len == n) { start = start->next; delete(start); } for (int i = 0; i < (len - n); i++) { temp1 = start; start = start->next; } temp1->next = start->next; delete(start); return; } 来源: CSDN 作者: technology_yu 链接: https://blog.csdn.net/u013436730/article/details/103616682

算法学习18-两个单链表相交的一系列问题

孤街醉人 提交于 2020-02-06 07:26:42
两个单链表相交的一系列问题 【题目】 在本题中,单链表可能有环,也可能无环。给定两个单链表的头节点 head1和head2,这两个链表可能相交,也可能不相交。请实现一个函数, 如果两个链表相交,请返回相交的第一个节点;如果不相交,返回null 即可。 要求:如果链表1的长度为N,链表2的长度为M,时间复杂度请达到 O(N+M),额外空间复杂度请达到O(1) 【思路】 我们可以把本题分解成三个问题 链表是否有环 解法一:利用哈希表解决问题 从第一个节点开始,如果哈希表中不存在,则把节点插入到哈希表中,如果存在的话,则此节点就是最后所求的节点。 解法二:不用哈希表解决问题(这是一个数学问题) 用两个指针,一个快指针,一个慢指针同时从单链表头部开始遍历,一快一慢: 若无环,肯定快指针先遍历到null,此时单链表无环. 若单链表有环,这两个指针肯定在环中相遇,相遇时,让快指针从头head开始遍历,然后放慢速度跟慢指针一样快,两个继续同时向下遍历,直到相遇,此时就是单链表入环节点。 两个链表是否相交,相交的第一个节点是在什么位置 两个无环单链表是否相交 解法一:利用哈希表解决问题 1.把链表一中所有的节点放到哈希表中 2.遍历第二个链表,每个元素在map中是否存在,第一个存在的节点即为相交的第一个节点,如果到达最后都没有的话,及两个链表中不存在链表。 解法二:不利用哈希表解决问题 1

leetcode-23 合并K个排序链表

风格不统一 提交于 2020-02-06 05:17:54
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。 示例: 输入 : [ 1->4->5, 1->3->4, 2->6 ] 输出 : 1->1->2->3->4->4->5->6 方法一: 使用vector数组存多个链表的所有节点,进行从小到大的排序,完成后再进行元素的指向,从第一个元素指向最后一个元素 bool cmp ( ListNode * l1 , ListNode * l2 ) { return l1 -> val < l2 -> val ; } ListNode * mergeKLists ( vector < ListNode * > & lists ) { vector < ListNode * > node_vec ; for ( int i = 0 ; i < lists . size ( ) ; ++ i ) { while ( lists [ i ] ) { node_vec . push_back ( lists [ i ] ) ; lists [ i ] = lists [ i ] -> next ; } } if ( node_vec . size ( ) == 0 ) { return NULL ; } //从小到大排序 std : : sort ( node_vec . begin ( ) , node_vec . end (

ConcurrentHashMap和HashTable的区别

℡╲_俬逩灬. 提交于 2020-02-06 05:10:51
ConcurrentHashMap和HashTable的区别 底层数据结构:ConcurrentHashMap在JDK1.7时,底层采用 分段数组+链表 形式;JDK1.8以后和HashMap一样采用 数组+链表/红黑二叉树 ,HashTable和JDK1.8以前的HashMap一样的底层数据结构: 数组+链表 ,数组是HashMap的主体,链表是为了解决哈希冲突问题; 实现线程安全方式: 1、在JDK1.7时,ConcurrentHashMap对数组进行了分端分割(Segment),每一把锁只锁容器中的一部分数据,多线程访问容器中不同数据段数据,不会发生锁竞争,提高并发访问效率;在JDK1.8时,摒弃分端分割(Segment)概念,直接采用数组+链表+红黑树的数据结构,并发控制采用synchronized和CAS操作,相当于是优化过的HashMap,JDK1.8中的Segment是简化过的属性,为了兼容旧版本; 2、HashTable(同一把锁):采用synchronized保证线程安全,效率低下;当多个线程访问同步方法时,会发生阻塞或轮询状态;当一个线程使用put()方法添加元素时,另一个线程不能使用put()方法添加元素,也不能使用get()方法,竞争会越来越激烈。 来源: CSDN 作者: 爱敲代码的程序媛 链接: https://blog.csdn.net/qq