在开始讨论链表和队列前,先回顾一下课堂上讲授的数组内容。数组是java中最基本的数据结构,可以将其理解为一个容器,即可以用数组来装东西。但数组这个这个容器,在其定义的时候,它的长度就是固定的了。因此,在使用的时候,难免会有各种限制,这样的代码是死板呆滞。由此 ,引入了队列和链表这两种数据结构,它们和数组最大区别是:可以实现自动增长。
新建一个一个队列类,可以定义其初始的长度(容量)和每次增加的个数,添加,插入,删除元素及返回队列长度的方法。
public class Queue3 { //数组的初始长度和每次增加个数 private int initLen; private int increaseNum; //设置一个计数器,初始值为0,用来检测数组是否越界,也作为测量队列长度 private int count = 0; //长度为 initLen的数组 int [] oldQ = new int[initLen]; Queue3(int initLen, int increaseNum){ this.initLen = initLen ; this.increaseNum = increaseNum; } Queue3(){ this(3,3); } //数组添加元素的方法 public void add(int o){ //判断是否出现越界 if(count < oldQ.length){ oldQ[count] = o; count++; }else{ //一个新数组,长度为原数组+increaseNum int [] newQ = new int[oldQ.length+increaseNum]; //新数组赋值 for(int i=0;i < oldQ.length ;i++){ newQ[i] = oldQ[i]; } newQ[oldQ.length] = o; count++; //两数组互换 oldQ = newQ; } } //返回数组中的值的方法 public int get(int index){ return oldQ[index]; } //删除数组中指定位置的值的方法 public int delete(int index){ int tmp; //判断位置是否有效 if(index <0 && index >= oldQ.length){ tmp=99999999; }else{ int [] newQ = new int[oldQ.length-1]; tmp = oldQ[index]; for(int i=0 ; i < index ; i++){ newQ[i] = oldQ[i]; } for(int i=index;i < oldQ.length-1 ;i++){ newQ[i] = oldQ[i+1]; } // oldQ = newQ; } return tmp; } //在指定位置插入元素的方法 public void insert(int index,int o){ //判断index的位置是否合法 if(index < 0 && index >= oldQ.length){ }else { //新建一个长度+1的数组 int newQ [] = new int[oldQ.length+1]; //新数组赋值 newQ[index] = o ; for(int i=0;i < index; i++){ newQ[i] = oldQ[i] ; } for( int i= index+1; i<oldQ.length;i++){ newQ[i] = oldQ[i-1]; } //交换 oldQ=newQ; } } //求长度的方法 public int size(){ return oldQ.length; } }
实际上,队列就是对数组的一个升级版,他们都是顺序存储结构的。而链表是链式存储结构。实现链表,我用了两个类,Node类和 List类。
public class Node1 { private int data; private Node1 next; //设置节点的数据 public void setData(int o){ this.data = o; } public int getData(){ return data; } //设置下一个节点 public void setNext(Node1 n){ this.next = n; } //返回下一个节点 public Node1 getNext(){ return this.next; } } public class List1 { //链表的属性,头节点 private Node1 root; //链表的最后一个节点 private Node1 tail; public List1(Node1 root,Node1 tail) { this.root = root; this.tail = tail; } public void setRoot(Node1 n){ root=n; } //链表添加节点 public void add(Node1 n){ if( root.equals(tail) ){ root.setNext(n); tail = n; }else{ tail.setNext(n); tail = n; } } //找到指定位置的节点 public Node1 Query(int index){ Node1 tem = root ; while(index > 0){ tem = tem.getNext(); index--; } return tem; } //返回指定节点的值 public int getData(int index){ return this.Query(index).getData(); } //链表在指定位置后面插入节点 public void insert(Node1 n , int index){ //定位到指定位置的节点 Node1 n0 = this.Query(index); //n指向n0的下一个 n.setNext( n0.getNext() ); //n0指向n n0.setNext(n); } //删除指定位置的节点,并返回其内容 public int delete(int index){ //找到指定位置的节点 Node1 n =this.Query(index); //如果要删除头节点,则把第二个节点设为头节点 if(index ==0){ root = root.getNext(); }else{ //找到指定位置的前一个节点 Node1 n0 = this.Query(index-1); //找到指定位置的后一个节点 Node1 n1 = this.Query(index+1); //删除 n0.setNext(n1); } //返回删除节点的内容 return n.getData(); //从安全角度考虑,把删除的n指向空,但会报错 //n.setNext(null); } }
接着 ,就可以测试比较队列和链表了。主要比较的是他们 查找 、 插入、 删除性能上的差异。从理论上来分析,队列是顺序结构,数据是一个挨着一个存储的,就像战士们排成一队,链表就相当于一跟线把数据给串起来,不难想象,在查找上,队列的肯定比链表快。而在插入和删除上,和现实生活中类似,插队等举动总是让队伍越派越长,插入和删除在队列中的实现比较麻烦。而链表就如同把一根绳剪断,在断处用新的接上,所以实现起来很快。
究竟是怎样,可以编程来直观地体现。借助System.currentTimeMillis()方法,该函数返回1970年1月1日0时起的毫秒数,因此可以在代码的头和尾都设置这么一个函数,就可以求出这段代码的运行时间了。
测试队列
public class TestQ3 { public static void main(String[] args) { // TODO Auto-generated method stub //生成一个队列 Queue3 q = new Queue3(0,1); for(int i=0; i< 100000 ;i++){ q.add(i); } //查找 Random rand = new Random(); long start1=System.currentTimeMillis(); for(int i=0;i <= 1000; i++){ int x=rand.nextInt(99999); q.get(x); } long end1=System.currentTimeMillis(); long cost1 = start1 - end1; System.out.println("返回时间"+cost1); //插入 long start2=System.currentTimeMillis(); for(int i=0;i <= 1000; i++){ int x=rand.nextInt(99999); q.insert(x, 0); } long end2=System.currentTimeMillis(); long cost2 = end2 - start2 ; System.out.println("插入时间"+cost2); //删除 long start3=System.currentTimeMillis(); for(int i=0;i <= 1000; i++){ int x=rand.nextInt(99990-i); q.delete(x); } long end3=System.currentTimeMillis(); long cost3 = end3 - start3 ; System.out.println("删除使用时间"+cost3); } }
测试链表
public class NodeTest1 { public static void main(String [] args){ Node1 n0 = new Node1(); n0.setData(0); List1 l = new List1(n0,n0); //生成包含10w个节点的链表 for(int i=1 ; i<= 100000; i++){ Node1 n = new Node1(); n.setData(i); l.add(n); } //返回节点的值 Random rand = new Random(); long start1=System.currentTimeMillis(); for(int i=0;i <= 1000; i++){ int x=rand.nextInt(99999); l.getData(x); } long end1=System.currentTimeMillis(); long cost1 = start1 - end1; System.out.println("查找使用时间"+cost1); //插入 long start2=System.currentTimeMillis(); Node1 n = new Node1(); for(int i=0;i <= 1000; i++){ int x=rand.nextInt(99999); l.insert(n, x); } long end2=System.currentTimeMillis(); long cost2 = end2 - start2 ; System.out.println("插入使用时间"+cost2); //删除 long start3=System.currentTimeMillis(); for(int i=0;i <= 1000; i++){ int x=rand.nextInt(80000); l.delete(x); } long end3=System.currentTimeMillis(); long cost3 = end3 - start3 ; System.out.println("删除使用时间"+cost3); } }
结果是 队列 链表
查找 1 165
插入 853 54
删除 846 472
此结果和之前的理论分析是一致的。
这就是队列和链表的简单应用和分析了。在听课时,老师还谈到,删除节点时,为了安全,应把所删节点指向空值,但我设置它指向空的话,会报错。不知道这该怎么做,望各路过大牛指导。
相关推荐
本篇文章将详细讲解Java中的队列、链表和栈,这些概念是许多初学者和专业人士都需要掌握的基础知识。 首先,我们来谈谈队列。队列是一种先进先出(First In First Out,简称FIFO)的数据结构,类似于现实生活中的...
学习和理解堆栈和队列的链表实现对理解数据结构和算法至关重要,它们在递归、回溯、任务调度、内存管理等许多领域都有应用。通过编写和运行这些程序,可以加深对这些概念的理解,并提升编程能力。在实际开发中,掌握...
Java中的队列是一种数据结构,它遵循先进先出(FIFO)原则,即最先插入的元素将是最先被删除的。在Java中,队列的实现主要有三种:顺序队列、链式队列和循环队列。下面我们将详细探讨这三种队列的实现方式。 1. **...
通过学习和理解这些源代码,你可以深入理解栈和队列的工作原理,提高解决实际问题的能力,并为面试和项目开发积累宝贵的经验。同时,这些例子还可以帮助你熟悉Java的容器类库,比如ArrayList、LinkedList和Queue接口...
在Java编程语言中,`Queue`接口是集合框架的一部分,它代表了先进先出(FIFO)的数据结构,也就是我们通常所说的队列。队列是一种非常基础且实用的数据结构,广泛应用于多线程同步、任务调度、缓存管理等多个场景。...
在Java编程语言中,链表是一种重要的数据结构,它与数组不同,不依赖于内存中的连续空间。链表由一系列节点组成,每个节点包含数据和指向下一个节点的引用。本篇将深入探讨如何在Java中实现单链表,包括其基本操作、...
Java中的阻塞队列是一种基于同步原语的高级数据结构,它在多线程编程中扮演着重要角色,尤其在并发处理和优化系统资源利用率方面。阻塞队列结合了队列的数据结构与线程同步机制,使得生产者可以在队列满时被阻塞,而...
本文将结合个人学习心得,深入探讨Java链表的核心概念、实现方式以及与其他编程语言的互通性。 首先,链表是一种线性数据结构,与数组不同,它的元素在内存中不是连续存储的。每个元素(称为节点)包含两部分:数据...
Java 中的双端队列(Deque)是一种特殊的队列,能够在队列的两端进行元素的添加和删除操作。与单端队列不同,双端队列可以在队列的头部和尾部同时进行插入和删除操作。 Java 实现自定义双端队列可以通过链表和数组...
`FirstLastLinkList.java`可能是一个实现双向链表的类,其命名暗示了它主要关注链表的首尾操作,类似于栈或队列。在这个类中,我们可能会找到类似的方法,如`addFirst()`, `addLast()`, `removeFirst()`, 和 `...
假设以带头结点的循环链表表示一个队列,并且只设一个队尾指针指向尾元素结点(注意不设头指针),试写出相应的置空队、入队、出队的算法。(Java描述)
arithmetic java算法冒泡排序、二叉树、数组、链表、队列学习简单示例 private static void mpSoft(String [] data) { for (int i = 0; i ; i++) { System.out.println(Arrays.toString(data)); for (int j = 0; ...
在"Part03Queue"这个压缩包中,可能包含了关于如何在Java中实现环形队列的代码示例,通过学习这部分内容,你可以深入了解环形队列的内部机制,并能熟练地在自己的项目中运用。此外,"bearqu5"可能是一个开发者的名字...
环形队列是一种特殊形式的线性数据结构,它的特点是队尾和队首可以在数组的最后一个元素和第一个元素之间循环移动,从而实现高效的数据插入和删除操作。在Java中实现环形队列,通常会使用数组或链表作为底层数据容器...
在这个主题中,我们将深入探讨Java中队列的实现,包括顺序队列(SqQueueCycle)和链队列(LinkQueue)。 1. **队列的基本概念** 队列是一种线性数据结构,遵循“先进先出”(FIFO,First In First Out)原则。它...
队列和堆栈是两种基础但非常重要的数据结构,它们在Java编程中有着广泛的应用。本篇将详细介绍基于Java实现的队列和堆栈,并探讨它们的工作原理、实现方式以及实际应用。 1. **队列(Queue)** - **定义**:队列是...
总的来说,这个练习通过`Queue.java`和`Node.java`文件,旨在帮助学习者理解如何在Java中实现数据结构——队列,以及如何利用链表作为底层存储结构。这样的练习有助于提高对数据结构的理解,为编写更复杂、高效的...
本资源提供了Java实现的数据结构代码,包括栈、动态数组、队列、链表和二叉树,这些都是计算机科学中最基础且重要的数据结构。 1. **栈(Stack)**:栈是一种“后进先出”(LIFO)的数据结构,常用于表达式求值、...
总结来说,使用Java链表实现多项式相加是一种直观且有效的方法。通过链表的特性,我们可以方便地管理多项式的各项,并进行相应的计算。这个过程不仅锻炼了数据结构和算法的应用能力,也提高了代码的可读性和可维护性...
在Java编程语言中,阻塞队列是一种线程安全的数据结构,它在多线程并发控制中发挥着重要作用。阻塞队列的核心特性是当队列为空时,尝试获取元素的线程会被阻塞,直到其他线程添加元素;同样,当队列满时,试图插入...