Java数据结构与经典算法——高手必会
- 格式:doc
- 大小:1.08 MB
- 文档页数:79
java 经典笔试算法题一、排序算法1. 实现一个基于Java的快速排序算法。
答:快速排序是一种常用的排序算法,其核心思想是分治法。
首先选择一个基准元素,将数组分成两部分,一部分小于基准元素,一部分大于基准元素。
然后递归地对这两部分继续进行快速排序,直到整个数组有序。
2. 实现一个稳定的冒泡排序算法。
答:冒泡排序是一种简单的排序算法,通过重复地遍历待排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。
稳定的冒泡排序算法是指在排序过程中,相同元素的相对位置不会改变。
3. 实现一个选择排序算法。
答:选择排序是一种简单直观的排序算法。
其工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。
二、字符串操作算法1. 实现一个函数,将一个字符串反转。
答:可以使用StringBuilder类的reverse()方法来实现字符串的反转。
2. 实现一个函数,将一个字符串中的所有大写字母转换为小写字母,其余字符保持不变。
答:可以使用String类的replaceAll()方法和toLowerCase()方法来实现。
3. 实现一个函数,将一个字符串按空格分割成单词数组,并删除空字符串和null字符串。
答:可以使用split()方法和Java 8的流来处理。
三、数据结构算法1. 实现一个单向链表,并实现插入、删除、查找和打印链表的功能。
答:单向链表是一种常见的数据结构,可以通过定义节点类和链表类来实现。
插入、删除、查找和打印链表的功能可以通过相应的方法来实现。
2. 实现一个二叉搜索树(BST),并实现插入、查找、删除节点的功能。
答:二叉搜索树是一种常见的数据结构,它具有唯一的高度特性。
插入、查找和删除节点的功能可以通过相应的方法来实现,如左旋、右旋、递归等。
3. 实现一个哈希表(HashMap),并实现插入、查找和删除键值对的功能。
答:HashMap是一种基于哈希表的映射数据结构,它通过哈希码的方式将键映射到对应的值上。
Java数据结构和算法一、数组于简单排序 (1)二、栈与队列 (4)三、链表 (7)四、递归 (22)五、哈希表 (25)六、高级排序 (25)七、二叉树 (25)八、红—黑树 (26)九、堆 (36)十、带权图 (39)一、数组于简单排序数组数组(array)是相同类型变量的集合,可以使用共同的名字引用它。
数组可被定义为任何类型,可以是一维或多维。
数组中的一个特别要素是通过下标来访问它。
数组提供了一种将有联系的信息分组的便利方法。
一维数组一维数组(one-dimensional array )实质上是相同类型变量列表。
要创建一个数组,你必须首先定义数组变量所需的类型。
通用的一维数组的声明格式是:type var-name[ ];获得一个数组需要2步。
第一步,你必须定义变量所需的类型。
第二步,你必须使用运算符new来为数组所要存储的数据分配内存,并把它们分配给数组变量。
这样Java 中的数组被动态地分配。
如果动态分配的概念对你陌生,别担心,它将在本书的后面详细讨论。
数组的初始化(array initializer )就是包括在花括号之内用逗号分开的表达式的列表。
逗号分开了数组元素的值。
Java 会自动地分配一个足够大的空间来保存你指定的初始化元素的个数,而不必使用运算符new。
Java 严格地检查以保证你不会意外地去存储或引用在数组范围以外的值。
Java 的运行系统会检查以确保所有的数组下标都在正确的范围以内(在这方面,Java 与C/C++ 从根本上不同,C/C++ 不提供运行边界检查)。
多维数组在Java 中,多维数组(multidimensional arrays )实际上是数组的数组。
你可能期望,这些数组形式上和行动上和一般的多维数组一样。
然而,你将看到,有一些微妙的差别。
定义多维数组变量要将每个维数放在它们各自的方括号中。
例如,下面语句定义了一个名为twoD 的二维数组变量。
int twoD[][] = new int[4][5];简单排序简单排序中包括了:冒泡排序、选择排序、插入排序;1.冒泡排序的思想:假设有N个数据需要排序,则从第0个数开始,依次比较第0和第1个数据,如果第0个大于第1个则两者交换,否则什么动作都不做,继续比较第1个第2个…,这样依次类推,直至所有数据都“冒泡”到数据顶上。
数据结构与算法分析java——散列1. 散列的概念 散列⽅法的主要思想是根据结点的关键码值来确定其存储地址:以关键码值K为⾃变量,通过⼀定的函数关系h(K)(称为散列函数),计算出对应的函数值来,把这个值解释为结点的存储地址,将结点存⼊到此存储单元中。
检索时,⽤同样的⽅法计算地址,然后到相应的单元⾥去取要找的结点。
通过散列⽅法可以对结点进⾏快速检索。
散列(hash,也称“哈希”)是⼀种重要的存储⽅式,也是⼀种常见的检索⽅法。
按散列存储⽅式构造的存储结构称为散列表(hash table)。
散列表中的⼀个位置称为槽(slot)。
散列技术的核⼼是散列函数(hash function)。
对任意给定的动态查找表DL,如果选定了某个“理想的”散列函数h及相应的散列表HT,则对DL中的每个数据元素X。
函数值h(X.key)就是X在散列表HT中的存储位置。
插⼊(或建表)时数据元素X将被安置在该位置上,并且检索X时也到该位置上去查找。
由散列函数决定的存储位置称为散列地址。
因此,散列的核⼼就是:由散列函数决定关键码值(X.key)与散列地址h(X.key)之间的对应关系,通过这种关系来实现组织存储并进⾏检索。
⼀般情况下,散列表的存储空间是⼀个⼀维数组HT[M],散列地址是数组的下标。
设计散列⽅法的⽬标,就是设计某个散列函数h,0<=h( K ) < M;对于关键码值K,得到HT[i] = K。
在⼀般情况下,散列表的空间必须⽐结点的集合⼤,此时虽然浪费了⼀定的空间,但换取的是检索效率。
设散列表的空间⼤⼩为M,填⼊表中的结点数为N,则称为散列表的负载因⼦(load factor,也有⼈翻译为“装填因⼦”)。
建⽴散列表时,若关键码与散列地址是⼀对⼀的关系,则在检索时只需根据散列函数对给定值进⾏某种运算,即可得到待查结点的存储位置。
但是,散列函数可能对于不相等的关键码计算出相同的散列地址,我们称该现象为冲突(collision),发⽣冲突的两个关键码称为该散列函数的同义词。
java常用算法和数据结构Java是一种面向对象的编程语言,它具有丰富的算法库和数据结构库,为开发人员提供了许多常用的算法和数据结构。
下面将介绍一些Java常用的算法和数据结构。
1.排序算法-冒泡排序(Bubble Sort):比较相邻的两个元素,如果顺序错误则交换位置,重复该过程直到整个序列有序。
-插入排序(Insertion Sort):将数组分为已排序和未排序两部分,每次从未排序部分取出一个元素,插入到已排序部分合适的位置。
-选择排序(Selection Sort):每次从未排序部分选择最小(或最大)的元素,放到已排序部分的末尾。
-快速排序(Quick Sort):选择一个基准元素,将数组分为两部分,小于基准的放左边,大于基准的放右边,递归地对左右两部分进行快速排序。
-归并排序(Merge Sort):将数组分为两部分,分别对每个子数组进行排序,然后合并两个有序子数组。
2.搜索算法-二分查找(Binary Search):对有序数组进行查找,每次将查找范围缩小一半。
-广度优先搜索(BFS):以树或图的形式搜索,从根节点开始,逐层扩展搜索范围,直到找到目标节点。
-深度优先搜索(DFS):以树或图的形式搜索,从根节点开始,逐个访问节点的所有邻居节点,直到找到目标节点或搜索完所有节点。
3.数据结构-数组(Array):一组按顺序存储的相同类型元素的集合,通过索引访问元素,可以快速访问元素,但插入和删除元素较慢。
-链表(Linked List):一组通过指针连接的节点存储的元素的集合,支持灵活的插入和删除操作,但访问元素较慢。
-栈(Stack):一种特殊的线性数据结构,遵循先进后出(LIFO)原则,只能在栈顶进行插入和删除操作。
-队列(Queue):一种特殊的线性数据结构,遵循先进先出(FIFO)原则,在队尾插入元素,队头删除元素。
-堆(Heap):一种特殊的树形数据结构,可以快速找到最小(或最大)元素,常用于实现优先队列。
java面试题经典算法经典算法在Java面试中经常被问及,因为它们可以展示面试者对基本数据结构和算法的理解程度。
以下是一些经典算法,我会逐个介绍它们。
1. 冒泡排序(Bubble Sort),这是一种简单的排序算法,它重复地走访要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。
时间复杂度为O(n^2)。
2. 快速排序(Quick Sort),快速排序使用分治法策略来把一个序列分为两个子序列。
它是一种分而治之的算法,时间复杂度为O(nlogn)。
3. 二分查找(Binary Search),二分查找是一种在有序数组中查找某一特定元素的搜索算法。
时间复杂度为O(logn)。
4. 递归算法(Recursion),递归是指在函数的定义中使用函数自身的方法。
递归算法通常用于解决可以被分解为相同问题的子问题的情况。
5. 动态规划(Dynamic Programming),动态规划是一种在数学、计算机科学和经济学中使用的一种方法。
它将问题分解为相互重叠的子问题,通过解决子问题的方式来解决原始问题。
6. 深度优先搜索(Depth-First Search)和广度优先搜索(Breadth-First Search),这两种搜索算法通常用于图的遍历和搜索。
深度优先搜索使用栈来实现,而广度优先搜索则使用队列来实现。
以上是一些常见的经典算法,当然还有很多其他的算法,如贪心算法、Dijkstra算法、KMP算法等等。
在面试中,除了了解这些算法的原理和实现方式之外,还需要能够分析算法的时间复杂度、空间复杂度以及适用场景等方面的知识。
希望这些信息能够帮助你在Java面试中更好地准备算法相关的问题。
Java常见的七种查找算法1. 基本查找也叫做顺序查找,说明:顺序查找适合于存储结构为数组或者链表。
基本思想:顺序查找也称为线形查找,属于无序查找算法。
从数据结构线的一端开始,顺序扫描,依次将遍历到的结点与要查找的值相比较,若相等则表示查找成功;若遍历结束仍没有找到相同的,表示查找失败。
示例代码:public class A01_BasicSearchDemo1 {public static void main(String[] args){//基本查找/顺序查找//核心://从0索引开始挨个往后查找//需求:定义一个方法利用基本查找,查询某个元素是否存在//数据如下:{131, 127, 147, 81, 103, 23, 7, 79}int[] arr ={131,127,147,81,103,23,7,79};int number =82;System.out.println(basicSearch(arr, number));}//参数://一:数组//二:要查找的元素//返回值://元素是否存在public static boolean basicSearch(int[] arr,int number){//利用基本查找来查找number在数组中是否存在for(int i =0; i < arr.length; i++){if(arr[i]== number){return true;}}return false;}}2. 二分查找也叫做折半查找,说明:元素必须是有序的,从小到大,或者从大到小都是可以的。
如果是无序的,也可以先进行排序。
但是排序之后,会改变原有数据的顺序,查找出来元素位置跟原来的元素可能是不一样的,所以排序之后再查找只能判断当前数据是否在容器当中,返回的索引无实际的意义。
基本思想:也称为是折半查找,属于有序查找算法。
用给定值先与中间结点比较。
比较完之后有三种情况:•相等说明找到了•要查找的数据比中间节点小说明要查找的数字在中间节点左边•要查找的数据比中间节点大说明要查找的数字在中间节点右边代码示例:package com.itheima.search;public class A02_BinarySearchDemo1 {public static void main(String[] args){//二分查找/折半查找//核心://每次排除一半的查找范围//需求:定义一个方法利用二分查找,查询某个元素在数组中的索引//数据如下:{7, 23, 79, 81, 103, 127, 131, 147}int[] arr ={7,23,79,81,103,127,131,147};System.out.println(binarySearch(arr,150));}public static int binarySearch(int[] arr,int number){//1.定义两个变量记录要查找的范围int min =0;int max = arr.length-1;//2.利用循环不断的去找要查找的数据while(true){if(min > max){return-1;}//3.找到min和max的中间位置int mid =(min + max)/2;//4.拿着mid指向的元素跟要查找的元素进行比较if(arr[mid]> number){//4.1 number在mid的左边//min不变,max = mid - 1;max = mid -1;}else if(arr[mid]< number){//4.2 number在mid的右边//max不变,min = mid + 1;min = mid +1;}else{//4.3 number跟mid指向的元素一样//找到了return mid;}}}}3. 插值查找在介绍插值查找之前,先考虑一个问题:为什么二分查找算法一定要是折半,而不是折四分之一或者折更多呢?其实就是因为方便,简单,但是如果我能在二分查找的基础上,让中间的mid点,尽可能靠近想要查找的元素,那不就能提高查找的效率了吗?二分查找中查找点计算如下:mid=(low+high)/2, 即mid=low+1/2*(high-low);我们可以将查找的点改进为如下:mid=low+(key-a[low])/(a[high]-a[low])*(high-low),这样,让mid值的变化更靠近关键字key,这样也就间接地减少了比较次数。
java 栈的常用方法Java中的栈是一种常见的数据结构,它具有后进先出(LIFO)的特点,即最后入栈的元素最先出栈。
在Java中,栈的常用方法包括push、pop、peek、isEmpty和size等。
本文将详细介绍这些方法的功能和用法。
1. push方法:该方法用于将元素压入栈顶。
在Java中,可以使用push方法将元素添加到栈中。
例如,可以使用以下代码将一个整数元素压入栈中:```Stack<Integer> stack = new Stack<>();stack.push(10);```2. pop方法:该方法用于从栈顶弹出一个元素。
在Java中,可以使用pop方法从栈中弹出元素。
例如,可以使用以下代码从栈中弹出一个整数元素:```int element = stack.pop();```3. peek方法:该方法用于获取栈顶的元素,但不将其从栈中移除。
在Java中,可以使用peek方法获取栈顶元素。
例如,可以使用以下代码获取栈顶的整数元素:```int topElement = stack.peek();```4. isEmpty方法:该方法用于判断栈是否为空。
在Java中,可以使用isEmpty方法判断栈是否为空。
例如,可以使用以下代码判断栈是否为空:```boolean empty = stack.isEmpty();```5. size方法:该方法用于获取栈中元素的个数。
在Java中,可以使用size方法获取栈中元素的个数。
例如,可以使用以下代码获取栈中元素的个数:```int size = stack.size();```除了上述常用的栈方法,Java中的栈还提供了一些其他方法,如search方法和toArray方法。
6. search方法:该方法用于查找指定元素在栈中的位置。
在Java中,可以使用search方法查找元素在栈中的位置。
例如,可以使用以下代码查找一个整数元素在栈中的位置:```int position = stack.search(10);```7. toArray方法:该方法用于将栈中的元素转换为数组。
java递归算法经典题目递归是一种常见的算法思想,它通过将问题分解为更小的子问题来解决问题。
在Java中,递归算法可以用于解决许多经典问题,如斐波那契数列、汉诺塔、阶乘等。
下面我们将介绍一些Java递归算法经典题目,帮助您更好地理解和掌握递归算法。
1.斐波那契数列斐波那契数列是一个经典的递归问题,它是指从第0项开始,每一项都是前两项的和。
在Java中,可以使用递归方法来求解斐波那契数列。
以下是一个简单的递归算法实现:```javapublicstaticintfibonacci(intn){if(n<=1){returnn;}else{returnfibonacci(n-1)+fibonacci(n-2);}}```这个算法会一直递归调用直到达到斐波那契数列的末项为止。
需要注意的是,递归算法的时间复杂度较高,当n值较大时可能会导致栈溢出等问题。
2.汉诺塔问题汉诺塔问题是一个经典的递归问题,它描述了一个操作:将一堆盘子从一个柱子移动到另一个柱子,要求遵循以下规则:每次只能移动一个盘子,并且大盘子不能放在小盘子上面。
在Java中,可以使用递归方法来解决汉诺塔问题。
以下是一个简单的递归算法实现:```javapublicstaticvoidhanoi(intn,Stringfrom,Stringto,Stringvia) {if(n==1){System.out.println("Movedisk"+n+"from"+from+"to"+to);}else{hanoi(n-1,from,via,to);System.out.println("Movedisk1from"+from+"to"+to);hanoi(n-1,via,to,from);}}```这个算法会一直递归调用,直到完成所有盘子的移动。
数据结构与算法分析java课后答案【篇一:java程序设计各章习题及其答案】>1、 java程序是由什么组成的?一个程序中必须有public类吗?java源文件的命名规则是怎样的?答:一个java源程序是由若干个类组成。
一个java程序不一定需要有public类:如果源文件中有多个类时,则只能有一个类是public类;如果源文件中只有一个类,则不将该类写成public也将默认它为主类。
源文件命名时要求源文件主名应与主类(即用public修饰的类)的类名相同,扩展名为.java。
如果没有定义public类,则可以任何一个类名为主文件名,当然这是不主张的,因为它将无法进行被继承使用。
另外,对applet小应用程序来说,其主类必须为public,否则虽然在一些编译编译平台下可以通过(在bluej下无法通过)但运行时无法显示结果。
2、怎样区分应用程序和小应用程序?应用程序的主类和小应用程序的主类必须用public修饰吗?答:java application是完整的程序,需要独立的解释器来解释运行;而java applet则是嵌在html编写的web页面中的非独立运行程序,由web浏览器内部包含的java解释器来解释运行。
在源程序代码中两者的主要区别是:任何一个java application应用程序必须有且只有一个main方法,它是整个程序的入口方法;任何一个applet小应用程序要求程序中有且必须有一个类是系统类applet的子类,即该类头部分以extends applet结尾。
应用程序的主类当源文件中只有一个类时不必用public修饰,但当有多于一个类时则主类必须用public修饰。
小应用程序的主类在任何时候都需要用public来修饰。
3、开发与运行java程序需要经过哪些主要步骤和过程?答:主要有三个步骤(1)、用文字编辑器notepad(或在jcreator,gel, bulej,eclipse, jbuilder等)编写源文件;(2)、使用java编译器(如javac.exe)将.java源文件编译成字节码文件.class;(3)、运行java程序:对应用程序应通过java解释器(如java.exe)来运行,而对小应用程序应通过支持java标准的浏览器(如microsoft explorer)来解释运行。
java数据结构算法面试题面试对于求职者来说是一个重要的环节,尤其是对于计算机专业的求职者来说,数据结构和算法是面试中经常涉及的重要话题。
掌握Java数据结构和算法面试题,对于成功通过面试至关重要。
本文将介绍一些常见的Java数据结构和算法面试题,并给出相应的解答。
一、数组1. 给定一个整数数组,如何找到其中的最大值和最小值?解答:可以使用遍历数组的方式比较每个元素与当前的最大值和最小值,更新最大值和最小值。
2. 给定一个整数数组,如何找到其中两个数的和等于指定的目标值?解答:可以使用两层循环遍历数组,对每对不同的数进行求和判断是否等于目标值。
二、链表1. 如何实现链表的反转?解答:可以创建一个新的链表,然后遍历原链表,将原链表的每个节点插入到新链表的头部即可。
2. 如何判断链表中是否存在环?解答:可以使用快慢指针的方式遍历链表,如果存在环,则快指针最终会追上慢指针。
三、栈和队列1. 如何使用栈实现队列?解答:可以使用两个栈,一个用于入队操作,另一个用于出队操作。
当进行出队操作时,如果出队的栈为空,则需要将入队的栈中的元素依次出栈并入队栈,然后再出队。
2. 如何使用队列实现栈?解答:可以使用两个队列,一个用于入栈操作,另一个用于出栈操作。
当进行出栈操作时,需要将入栈的队列中的元素依次出队并入出栈的队列,直到剩下一个元素,即为需要出栈的元素。
四、排序算法1. 如何实现快速排序算法?解答:快速排序算法是一种分治算法,基本思想是选择一个基准元素,将数组分成两个子数组,小于基准元素的放在左边,大于基准元素的放在右边,然后递归地对子数组进行排序。
2. 如何实现归并排序算法?解答:归并排序算法也是一种分治算法,基本思想是将数组递归地分成两个子数组,然后合并两个有序的子数组,最终得到一个有序的数组。
五、查找算法1. 如何实现二分查找算法?解答:二分查找算法是一种分而治之的思想,首先将数组按照中间元素划分为两个子数组,然后判断目标值与中间元素的大小关系,从而确定目标值在哪个子数组中,然后递归地进行查找。
1.大O表示法:粗略的量度方法即算法的速度是如何与数据项的个数相关的算法大O表示法表示的运行时间线性查找 O(N)二分查找 O(logN)无序数组的插入 O(1)有序数组的插入 O(N)无序数组的删除 O(N)有序数组的删除 O(N)O(1)是最优秀的,O(logN)良好,O(N)还可以,O(N2)稍差(在冒泡法中见到)2.排序public class JWzw {//插入排序public void insertArray(Integer []in){int tem = 0;int num = 0;int upnum = 0;for (int i = 0; i < in.length; i++) {for (int j = i - 1; j >= 0; j--) {num++;if (in[j+1] < in[j]) {tem = in[j+1];in[j+1] = in[j];in[j] = tem;upnum++;}else{break;}}}for (int i = 0; i < in.length; i++) {System.out.print(in[i]);if(i < in.length - 1){System.out.print(",");}}System.out.println();System.out.println("插入排序循环次数:" + num);System.out.println("移动次数:" + upnum);System.out.print("\n\n\n");}//选择排序public void chooseArray(Integer []in){int tem = 0;int num = 0;int upnum = 0;for(int i = 0;i < in.length;i++){for(int j = i;j < in.length - 1;j++){num++;if(in[j+1] < in[j]){tem = in[j+1];in[j + 1] = in[j];in[j] = tem;upnum++;}}}for (int i = 0; i < in.length; i++) {System.out.print(in[i]);if(i < in.length - 1){System.out.print(",");}}System.out.println();System.out.println("选择排序循环次数:" + num);System.out.println("移动次数:" + upnum);System.out.print("\n\n\n");}//冒泡排序public void efferArray(Integer []in){int tem = 0;int num = 0;int upnum = 0;for(int i = 0;i < in.length;i++){for(int j = i;j < in.length - 1;j++){num++;if(in[j+1] < in[i]){tem = in[j+1];in[j+1] = in[i];in[i] = tem;upnum++;}}}for (int i = 0; i < in.length; i++) {System.out.print(in[i]);if(i < in.length - 1){System.out.print(",");}}System.out.println();System.out.println("冒泡排序循环次数:" + num);System.out.println("移动次数:" + upnum);System.out.print("\n\n\n");}//打印乘法口诀public void printMulti(){for (int j = 1; j < 10; j++) {for (int i = 1; i <= j; i++) {System.out.print(i + " * " + j + " = " + j * i + "\t");}System.out.print("\t\n");}System.out.print("\n\n\n");}//打印N * 1 + N * 2 + N * 3 =num的所有组合public void printNumAssemble(int num){for (int i = 0; i < num + 1; i++) {for (int j = 0; j < num / 2 +1; j++) {for (int in = 0; in < num / 3 + 1; in++) {if (i * 1 + j * 2 + in * 3 == num) {System.out.println("小马" + i + ",\t中马" + j + ",\t大马" + in);}}}}}/*** @param args*/public static void main(String[] args) {JWzw jwzw = new JWzw();int num = 3;jwzw.printMulti();//打印乘法口诀jwzw.printNumAssemble(100);//打印N * 1 + N * 2 + N * 3 =num的所有组合Integer in[] = {8,89,5,84,3,45,12,33,77,98,456,878,654,213,897};jwzw.efferArray(in);//冒泡排序Integer in1[] = {8,89,5,84,3,45,12,33,77,98,456,878,654,213,897};jwzw.insertArray(in1);//插入排序Integer in2[] = {8,89,5,84,3,45,12,33,77,98,456,878,654,213,897};jwzw.chooseArray(in2);//选择排序//int i = num++;//System.out.println(i);System.out.println(1000>>2);}}3.优先级队列class PriorityQueue {private long[] a = null;private int nItems = 0;private int maxSize = 0;public PriorityQueue(int maxSize) {a = new long[maxSize];this.maxSize = maxSize;nItems = 0;}public void insert(long l) {//优先级队列的插入不是队尾,而是选择一个合适的按照某种顺序插入的//当队列长度为0时,如下//不为0时,将所有比要插入的数小的数据后移,这样大的数就在队列的头部了int i = 0;if(nItems == 0) {a[0] = l;} else {for(i=nItems-1; i>=0; i--) {if(l < a[i])a[i+1] = a[i];elsebreak;}a[i+1] = l;}nItems++;}public long remove() {//移出的是数组最上端的数,这样减少数组元素的移动return a[--nItems];}public boolean isEmpty() {return (nItems == 0);}public boolean isFull() {return (nItems == maxSize);}public int size() {return nItems;}}public class duilie {// 队列体类private duilie s;private String data;duilie(String data) {this.data = data;}public String getData() {return data;}public void setData(String data) {this.data = data;}public duilie getS() {return s;}public void setS(duilie s) {this.s = s;}}public class duiliecz {// 队列操作类/*** @param args*/private int i = 0;// 队列长private duilie top = new duilie("");// 队列头private duilie end = new duilie("");// 队列尾public void add(String s) {// 添加队列duilie m = new duilie(s);if (i != 0) {m.setS(top.getS());top.setS(m);} else {top.setS(m);end.setS(m);}i++;}4.队列public void del() {// 删除队尾if (i == 0) {return;} else if (i == 1) {top.setS(null);end.setS(null);} else {duilie top1 = new duilie("");// 队列底查找用缓存 top1.setS(top.getS());while (!top1.getS().getS().equals(end.getS())) { top1.setS(top1.getS().getS());}end.setS(top1.getS());}i--;}public static void main(String[] args) {// TODO Auto-generated method stubduiliecz m = new duiliecz();m.add("1");m.add("2");m.add("3");m.add("4");for (int n = 0; n < 4; n++) {m.del();}}public int getI() {return i;}public duilie getEnd() {return end;}public duilie getTop() {return top;}}5.栈public class Stack {int[] arr;int len = 0;public Stack() {arr = new int[100];}public Stack(int n) {arr = new int[n];}public int size() {return len + 1;}// 扩大数组public void resize() {int[] b = new int[arr.length * 2];System.arraycopy(arr, 0, b, 0, arr.length);arr = b;}public void show() {for (int i = 0; i < len; i++) {System.out.print(arr[i] + " ");}System.out.println();}// 进栈public void push(int a) {if (len >= arr.length)resize();arr[len] = a;len++;}// 出栈public int pop() {if (len == 0) {System.out.println();System.out.println("stack is empty!");return -1;}int a = arr[len - 1];arr[len - 1] = 0;len--;return a;}}6.链表class Node {Object data;Node next;public Node(Object data) {setData(data);}public void setData(Object data) {this.data = data;}public Object getData() {return data;}}class Link {Node head;int size = 0;public void add(Object data) {Node n = new Node(data);if (head == null) {head = n;} else {Node current = head;while (true) {if (current.next == null) {break;}current = current.next;}current.next = n;}size++;}public void show() {Node current = head;if (current != null) {while (true) {System.out.println(current);if (current == null) {break;}current = current.next;}} else {System.out.println("link is empty");}}public Object get(int index) {// ....}public int size() {return size;}}7.单链表class Node // 节点类,单链表上的节点{String data; // 数据域,存放String类的数据Node next; // 指向下一个节点Node(String data) {this.data = data; // 构造函数}String get() {return data; // 返回数据}}class MyLinkList // 链表类{Node first; // 头节点int size; // 链表长度MyLinkList(String arg[]) {// Node first = new Node("head");//生成头节点first = new Node("head"); // J.F. 这里不需要定义局部变量 first// 如果定义了局部变量,那成员变量 first 就一直没有用上// 所以,它一直为空size = 0;Node p = first;for (int i = 0; i < arg.length; i++) // 将arg数组中的元素分别放入链表中{Node q = new Node(arg[i]);q.next = p.next; // 每一个节点存放一个arg数组中的元素p.next = q;p = p.next;size++;}}MyLinkList() // 无参数构造函数{// Node first = new Node("head");first = new Node("head"); // J.F. 这里犯了和上一个构造方法同样的错误size = 0;}int size() // 返回链表长度{return size;}void insert(Node a, int index) // 将节点a 插入链表中的第index个位置{Node temp = first;for (int i = 0; i < index; i++) {temp = temp.next;// 找到插入节点的前一节点}a.next = temp.next; // 插入节点temp.next = a;size++;}Node del(int index) // 删除第index个节点,并返回该值{Node temp = first;for (int i = 0; i < index; i++) {temp = temp.next;// 找到被删除节点的前一节点}Node node = temp.next;temp.next = node.next;size--; // 删除该节点,链表长度减一return node;}void print() // 在屏幕上输出该链表(这段程序总是出错,不知道错在哪里){Node temp = first;for (int i = 1; i < size; i++) // 将各个节点分别在屏幕上输出{temp = temp.next;System.out.print(temp.get() + "->");}}void reverse() // 倒置该链表{for (int i = 0; i < size; i++) {insert(del(size - 1), 0); // 将最后一个节点插入到最前// J.F. 最后一个节点的 index 应该是 size - 1// 因为第一个节点的 index 是 0}}String get(int index) // 查找第index个节点,返回其值{if (index >= size) {return null;}Node temp = first;for (int i = 0; i < index; i++) {temp = temp.next;// 找到被查找节点的前一节点}return temp.next.get();}}class MyStack // 堆栈类,用单链表实现{MyLinkList tmp;Node temp;MyStack() {// MyLinkList tmp = new MyLinkList();tmp = new MyLinkList(); // J.F. 和 MyLinkList 构造方法同样的错误}void push(String a) // 压栈,即往链表首部插入一个节点{Node temp = new Node(a);tmp.insert(temp, 0);}String pop() // 出栈,将链表第一个节点删除{Node a = tmp.del(0);return a.get();}int size() {return tmp.size();}boolean empty() // 判断堆栈是否为空{if (tmp.size() == 0)return false;elsereturn true;}}public class MyLinkListTest // 测试程序部分{public static void main(String arg[]) // 程序入口{if ((arg.length == 0) || (arg.length > 10))System.out.println("长度超过限制或者缺少参数");else {MyLinkList ll = new MyLinkList(arg); // 创建一个链表ll.print(); // 先输出该链表(运行到这一步抛出异常)ll.reverse(); // 倒置该链表ll.print(); // 再输出倒置后的链表String data[] = new String[10];int i;for (i = 0; i < ll.size(); i++) {data[i] = ll.get(i); // 将链表中的数据放入数组}// sort(data);// 按升序排列data中的数据(有没有现成的排序函数?)for (i = 0; i < ll.size(); i++) {System.out.print(data[i] + ";"); // 输出数组中元素}System.out.println();MyStack s = new MyStack(); // 创建堆栈实例sfor (i = 0; i < ll.size(); i++) {s.push(data[i]); // 将数组元素压栈}while (!s.empty()) {System.out.print(s.pop() + ";"); // 再将堆栈里的元素弹出}}}}8.双端链表class Link {public int iData = 0;public Link next = null;public Link(int iData) {this.iData = iData;}public void display() {System.out.print(iData + " ");}}class FirstLastList {private Link first = null;private Link last = null;public FirstLastList() {first = null;last = null;}public void insertFirst(int key) {Link newLink = new Link(key);if (this.isEmpty())last = newLink;newLink.next = first;first = newLink;}public void insertLast(int key) {Link newLink = new Link(key);if (this.isEmpty())first = newLink;elselast.next = newLink;last = newLink;}public Link deleteFirst() {Link temp = first;if (first.next == null)last = null;first = first.next;return temp;}public boolean isEmpty() {return (first == null);}public void displayList() {System.out.print("List (first-->last): ");Link current = first;while (current != null) {current.display();current = current.next;}System.out.println("");}}class FirstLastListApp {public static void main(String[] args) {// TODO Auto-generated method stubFirstLastList theList = new FirstLastList();theList.insertFirst(22); // insert at fronttheList.insertFirst(44);theList.insertFirst(66);theList.insertLast(11); // insert at reartheList.insertLast(33);theList.insertLast(55);theList.displayList(); // display the listtheList.deleteFirst(); // delete first two itemstheList.deleteFirst();theList.displayList(); // display again }}9.有序链表package arithmetic;class Link {public int iData = 0;public Link next = null;public Link(int iData) {this.iData = iData;}public void display() {System.out.print(iData + " ");}}class SortedList {private Link first = null;public SortedList() {first = null;}public void insert(int key) {Link newLink = new Link(key);Link previous = null;Link current = first;// while的第一个条件是没有到达链表的尾端,第二个是按顺序找到一个合适的位置while (current != null && key > current.iData) {previous = current;current = current.next;}// 如果是空表或者要插入的元素最小,则在表头插入keyif (current == first)first = newLink;elseprevious.next = newLink;newLink.next = current;}/*** 删除表头的节点** @return要删除的节点*/public Link remove() {Link temp = first;first = first.next;return temp;}public boolean isEmpty() {return (first == null);}public void displayList() {System.out.print("List (first-->last): ");Link current = first; // start at beginning of listwhile (current != null) // until end of list,{current.display(); // print datacurrent = current.next; // move to next link}System.out.println("");}}class SortedListApp {public static void main(String[] args) { // create new listSortedList theSortedList = new SortedList();theSortedList.insert(20); // insert 2 itemstheSortedList.insert(40);theSortedList.displayList(); // display listtheSortedList.insert(10); // insert 3 more itemstheSortedList.insert(30);theSortedList.insert(50);theSortedList.displayList(); // display listtheSortedList.remove(); // remove an itemtheSortedList.displayList(); // display list }}10.双向链表class Link {// 双向链表,有两个指针,一个向前,一个向后public int iData = 0;public Link previous = null;public Link next = null;public Link(int iData) {this.iData = iData;}public void display() {System.out.print(iData + " ");}}class DoublyLinked {// 分别指向链表的表头和表尾private Link first = null;private Link last = null;public boolean isEmpty() {return first == null;}/*** 在表头插入数据** @param要插入的节点的数据*/public void insertFirst(int key) {Link newLink = new Link(key);// 如果开始链表为空,则插入第一个数据后,last也指向第一个数据if (this.isEmpty())last = newLink;else {// 表不为空的情况first.previous = newLink;newLink.next = first;}// 无论怎样,插入后都的让first重新指向第一个节点first = newLink;}public void insertLast(int key) {// 在尾端插入数据,同上Link newLink = new Link(key);if (this.isEmpty())first = newLink;else {last.next = newLink;newLink.previous = last;}last = newLink;}/*** 在指定的节点后插入数据** @param key* 指定的节点的值* @param iData* 要插入的数据* @return是否插入成功*/public boolean insertAfter(int key, int iData) {Link newLink = new Link(key);Link current = first;// 从first开始遍历,看能否找到以key为关键字的节点while (current.iData != key) {current = current.next;// 若能找到就跳出循环,否则返回false,插入失败if (current == null)return false;}// 如果插入点在last的位置if (current == last) {last = newLink;} else {// 非last位置,交换各个next和previous的指针newLink.next = current.next;current.next.previous = newLink;}current.next = newLink;newLink.previous = current;return true;}/*** 删除表头的节点** @return*/public Link deleteFirst() {Link temp = first;// 如果表中只有一个元素,删除后则为空表,所以last=nullif (first.next == null)last = null;else// 否则,让第二个元素的previous=nullfirst.next.previous = null;// 删除头指针,则first指向原来的secondfirst = first.next;return temp;}public Link deleteLast() {// 同上Link temp = last;if (last.previous == null)first = null;elselast.previous.next = null;last = last.previous;return temp;}public Link deleteKey(int key) {Link current = first;// 遍历整个链表查找对应的key,如果查到跳出循环,否则...while (current.iData != key) {current = current.next;// ...否则遍历到表尾,说明不存在此key,返回null,删除失败if (current == null)return null;}if (current == first)first = first.next;elsecurrent.previous.next = current.next;if (current == last)last = last.previous;elsecurrent.next.previous = current.previous;return current;}public void displayForward() {Link current = first;while (current != null) {current.display();current = current.next;}System.out.println();}public void displayBackward() {Link current = last;while (current != null) {current.display();current = current.previous;}System.out.println();}}class DoublyLinkedApp {public static void main(String[] args) { // make a new list DoublyLinked theList = new DoublyLinked();theList.insertFirst(22); // insert at fronttheList.insertFirst(44);theList.insertFirst(66);theList.insertLast(11); // insert at reartheList.insertLast(33);theList.insertLast(55);theList.displayForward(); // display list forwardtheList.displayBackward(); // display list backwardtheList.deleteFirst(); // delete first itemtheList.deleteLast(); // delete last itemtheList.deleteKey(11); // delete item with key 11theList.displayForward(); // display list forwardtheList.insertAfter(22, 77); // insert 77 after 22theList.insertAfter(33, 88); // insert 88 after 33theList.displayForward(); // display list forward}}11.实现二叉树前序遍历迭代器class TreeNode 这个类用来声明树的结点,其中有左子树、右子树和自身的内容。