java 数据结构

本文介绍了数据结构的基础概念,包括数组和链表的使用,以及如何在Java中实现数组、双向链表、栈和队列。作者通过自定义的MyArray和MyLink类来实现这些数据结构,并与JDK的ArrayList和LinkedList进行对比。文章还提及了一个工具类Tool.java,简化了输出操作,并讨论了在不同环境下获取终端信息的挑战。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本人是一名出于兴趣的计算机爱好者,水品严重有限,有错误大家请了当指出,在下抱拳拱手以迎。

什么是数据结构,就是存储数据的一种手段,什么是程序程序就是算法和数据结构,其实程序只是处理数据,存储数据的方法是程序,但程序只加工数据,例如定义数据的存储结构,定义数据的使用方法。

数组是数据结构,但也可不用数组,我用变量也可以做到同样的效果,反正就是把数据存到内存上,我用变量存,和你用数组存都是一样的,但当数据多了就有问题了,比如存一百整数,我可以用100个变量存,但100个名字管理起来已经比100个数据还复杂了

,那我们把名字抹掉用索引,数组诞生,我讨厌数组的大块内存,我要把小块内存串起来,用一个分配一个,链表诞生。数据结构其实还可以叫做,数据存储的小方法更贴切一点,用最基本的数组和节点去构建一个庞大数据的存储方式,当然还有使用方法,如果只存不使用好像也没什么意义。

环境 : Ubuntu 18.04.1 LTS  + eclipse + JSE-10 。都是2018很新的软件,本项目eclipse导出项目源码百度网盘地址如下:https://pan.baidu.com/s/1ElG7VBsGAgvJZqcafLtu7w  任何问题请留言,或发送到邮箱gdYGDX@163.com

本篇内容:采用一站到底的方法,一篇博客把数组链表都实现一遍,然后再把栈和队列再都实现一遍,注意下面几点。

1.关于泛型的使用:泛型用起来很装逼其实什么屌用都没有请记住它只是编译的时候检查一下,后期运行时候都是被当成Object处理,但是好歹我们也是个实现,写的太low也不好交代,也不利于大家学习,所以我们逼格高一点,就搞个类库风格的数据结构只是前面都加了一个My单词,JDK有ArrayList 我们就搞一个MyArray,同时会有和JDK ArrayList的一些对比,JDK写的也不是太流弊,就是两点流弊,第一点:效率,同样的效果,人家知道整么写跑的快,这就流弊之一不得不服,第二:人家全局观吊环环相扣把面向对象耍的666,这是流弊之二不得不服。

2.链表是双向链表,保证是最奇怪的链表实现,因为完全是我自己想出来的就是为了好玩,当然也有一定的效果,我还想过球形链表把链表绕成一个球,然后有一个球心,球心还可以连接其它的球,后来搞得乱七八糟没任何意义,一个嵌套链表就搞定了,一个嵌套链表不行,那就再嵌套一个链表,不过嵌套到最后自己就不知道是什么鬼了。

3.工具类Tool.java 是模仿java编程思想写的一个工具类,println()方法等价与System.out.println()目的就是少打几个单词,看起来更美丽一点。好让我们进入代码的世界吧。

首先是Tool的源码,所有的其他类都静态引入了这个类,静态引入很爽只要你的方法是静态不用实例化也不用类名直接就可以调用了。

package dome.gaoxiaoming;

public class Tool {
	 public static void  println() {
		System.out.println();
	 }
	 public static void println(Object obj) {
		 System.out.println(obj);
	 }
	 public static void hr() {
		 Tool.println();
		 Tool.println("...................................................");
	 }
	 public static void hr(int how_long) {
		 Tool.println();
		 for(int i =0;i<how_long;i++) {
			 Tool.print(".");
		 }
		 Tool.println();
	 }
	 public static void print() {
		 System.out.print(" ");
	 }
	 public static void print(Object obj) {
		 System.out.print(obj);
	 }
	 
}

这些方法,90%都用不到,就天天只用到了一个println方法,那个hr()是打印华丽分割线,我后来想过获取终端长度然后我就可以打印一条和终端一样长的线了,后来在stackOverflow上找到了一个兄弟写的代码,他用OS的shell命令来获取终端的长度比如在linux 终端下输入tput cols 就和显示你的终端有多少列,列是竖着的也就是一行可以输入多少字符,tput lines 获取行数。

没想到的是eclipse下对终端进行了重定向,我也不知道是怎么从定向的,大概应该把系统的标准输入流定向到eclipse的终端,很像linux里的管道例如 ls | grep linux ,把ls的输出传给grep ,grep再查找有没有叫linux的,但重定向后问题就出来,那就是终端的信息丢失,传递的只有数据没有终端的描述,所以上面那个兄弟的代码在终端中可以用在eclipse终端下就无用,同理还有终端的密码输入不回显示方法在eclipse终端下也无法使用,说以我们就叫eclipse下的终端为太监终端。因为它被阉割了。关于那个StackOverflow兄弟的代码在项目里有名字叫做GetScreen.java顺手给大家。

开始正题 : 下面用数组实现java的ArrayList

package dome.gaoxiaoming;
/*
 * 表的数组实现,非末尾的插入删除都是 O(N^2) 所以效率很低,但是用下表擦找和遍历全
 * 表比链表操作要快,这也是数组的访问优势吧。 
 */
import static dome.gaoxiaoming.Tool.*;
import java.util.Iterator;
//泛型是为了提供检查机制,实现Iterable接口是为了使用forEach循环
public class MyArray<AnyType> implements Iterable<AnyType> {
/*
 * 用到的一些变量
 */
	private AnyType array[];
	private int size;
	private int DEFAULT_CAPACITY=10; //测试环境为10,实际使用建议调成100
	private float f_size,gxm_i=1,gxm_j=10; //这个跟自己的gxmSize方法有关,暂时可以忽略
	@SuppressWarnings("unchecked")   //忽略警告,下同
	public MyArray() {
		size=0;
		array = (AnyType[]) new Object[DEFAULT_CAPACITY];
	}
	public int getSize() {
		return size;
	}
	public int getCapacity() {
		return array.length;
	}
	
	@SuppressWarnings("unchecked")
	private void ensureCapacity(int newCapacity) {
		AnyType[] old = array;
		array = (AnyType[]) new Object[newCapacity];
		for(int i=0;i<old.length;i++) {
			array[i] = old[i];
		}
	}
/*
 * 下面是几个最基本的操作方法,像添加删除等等,一看名字就知道了	
 */
	public AnyType get(AnyType x) {
		for(int i=0;i<size;i++) {
			if(array[i]==x) {
				return array[i];
			}
		}
		return null;
	}
	public AnyType getDate(int index) {
		return array[--index];
	}
	public void change(int index,AnyType x) {
		if(index >= size) {
			return ;
		}
		array[index]=x;
	}
	public void remove(int index) {
		if(index>=size || index < 0) {
			return ;
		}
		if(size==array.length) {
			ensureCapacity(gxmSize());
		}
		for(int i=index;i<size;i++) {
			array[i]=array[i+1];
		}
		size--;
	}

	public void add(int index,AnyType x) {
		if(size==array.length) {
			ensureCapacity(gxmSize());
		}
		for(int i=size;i>index;i--) {
			array[i]=array[i-1];
		}
		array[index]=x;
		size++;
//		个人复杂的实现,没有从全局的眼光来添加
//		if(index>size) {
//			add(x);
//			return true;
//		}
//		for(int i=size-1;i>=index-1;i--) {
//			array[i+1]=array[i];
//		}
//		array[index-1]=x;
//		size++;
//		return true;
	}
	public void add(AnyType x) {
		add(size,x);
//		个人复杂的实现 没有从全局的眼光来实现	
//		if(size<array.length) {
//			array[size] = x;
//			++size;
//		}else if(size == array.length){
//			ensuerCapacity(size*2);
//			array[size] = x;
//			++size;
//		}else {
//			return false;
//		}	
//		return true;
	}
//基本操作方法结束

	public String toString() {
		StringBuilder std = new StringBuilder();
		std.append("[");
//优化之后不需要if判断更简洁高效		
		for(int i=0;i<size;i++) {
			std.append(array[i]+",");
		}
//用到if判断	
//		for(int i=0;i<size;i++) {
//			std.append(array[i]);
//			if(i<size-1) {
//				std.append(",");
//			}
//		}
		if(size != 0) {
			std.delete(std.length()-1,std.length());//去掉最后多余的逗号
		}
		std.append("]");
		return std.toString(); 
	}
/*
 * gxmSize()是一个我自己写的容量增加函数,一般也可以直接把现有的容量直接乘以一个常数,但当数值很大时分配的新
 * 空间有很大的空余,jdk中的扩容方法是扩容一半。而gxmSize()开始扩容大慢慢变慢,最后稳定下来,每次只增长原
 * 来的10%,因为数据在后期会比较稳定。	
 */
//	int newCapacity = oldCapacity + (oldCapacity >> 1); jdk 扩展方法 >>1 后数值上大致
//相当于除以2,这样写就是快,也是人家源码流弊的地方。
	private int gxmSize() {
		f_size=size;
		f_size +=(1-gxm_i/gxm_j)*size;
		if(gxm_i<9) {
			gxm_i++;
		}
		return (int)f_size;
	}

/*
 * (non-Javadoc)
 * @see java.lang.Iterable#iterator()
 * forEeach 需要实现Iterable接口,Iterable接口需要实现一个返回Iterator对象
 * 用内部类来作这块
 * 
 */
	public Iterator<AnyType> iterator() {
		
		return new MyArrayIterator<AnyType>();
	}
	@SuppressWarnings("hiding")
	class MyArrayIterator<AnyType> implements Iterator<AnyType>{
		int count=0;
		@Override
		public boolean hasNext() {
			// TODO Auto-generated method stub
			return count<size;
		}
		@SuppressWarnings("unchecked")
		@Override
		public AnyType next() {
			// TODO Auto-generated method stub
			if(!hasNext())
				throw new java.util.NoSuchElementException();
			return (AnyType) array[count++];
		}
		public void remove() {
			MyArray.this.remove(--count);
		}
	}
}

注释说的很清楚,只实现了基本的方法。

下面开始实现 java的LinkedList

package dome.gaoxiaoming;

import static dome.gaoxiaoming.Tool.*;

import java.util.Iterator;
/*
 * 链表的实现和数组有很多相识的地方,代码的风格实现的方法基本都很类似,所以不用说太多结合前面的ArrayList
 * 很容易就明白了。
 */
public class MyLink<AnyType> implements Iterable<AnyType> {
	public MyLink() {
		doClear();
	}
	@SuppressWarnings("all")
	/*
	 * 节点类,这里可以用static也可以不用static,用static则把Node节点看做是一个独立的区域,不依靠
	 * 父类就可以独立创建,没有static创建需要依赋父类.
	 * 因为静态类部类只能访问外部的静态成员,而普内部类还可以访问外部类非静态成员,所以当外部类环境没有正确
	 * 初始化则内部类就无法正确创建,顾对外部依赖性很强,所以当内部对外部没有依赖时,应该用静态内部类好一点。
	 * Node节点对外部没有任何依赖自己可以保持独立所以用静态较好,JDK的Node也是静态的。
	 */
	private static class Node<AnyType>{
		
		public AnyType date;
		public Node<AnyType> next,pre;
		public Node() {
		}
		public Node(AnyType date) {
			this.date = date;
		}
	}
	private Node<AnyType> head,tmp,cursor,end;
	private int length;
	public Node<AnyType> get_cursor() {
		return cursor;
	}
	public int getLegth() {
		return length;
	}
	public Node<AnyType> get_head() { //为后期的队列提供的方法
		return head.next;
	}
	public AnyType getDate(Node<AnyType> tmp) {
		return tmp.date;
	}
	public boolean empty() {
		return length == 0;
	} 
	/*
	 * 初始化链表,同时cursor初始指向head以后指向添加项保证顺序添加,顺序添加没有什么意义但看上去挺舒服
	 * 而且也不会让程序变慢。
	 * 
	 */
	public void doClear() {
		head = new Node<AnyType>();
		cursor = new Node<AnyType>();
		end = new Node<AnyType>();
		tmp = new Node<AnyType>();
		head.next = end;
		head.pre=null;
		end.pre = head;
		end.next=null;
		cursor = head;
		length=0;
	}
	public Node<AnyType> get(AnyType date) {
		Node<AnyType> target = new Node<AnyType>();
		target = head;
		while(target != end && target.date != date) {
			target = target.next;
		}
		return target;
	}
	public void remvoe(AnyType date) {
		if(cursor == get(date)) {
			cursor = cursor.pre;
		}
		tmp = get(date);
		tmp.pre.next = tmp.next;
		tmp.next.pre = tmp.pre;
		length--;
	}
	
	public void add(AnyType date) {
		Node<AnyType> nNode = new Node<AnyType>(date);
		nNode.next = cursor.next;
		nNode.pre = cursor;
		cursor.next.pre = nNode;
		cursor.next = nNode;
		cursor = nNode;
		length++;
/*
 * 分两种情况添加的方法,这种方法没有统观全局,可以用一种情况完成添加的操作。
 */
//		Node newNode = new Node(date);
//		if(length==0) {
//			head.next=newNode;
//			newNode.next=end;
//			length++;
//			return;
//		}
//		newNode.next=head.next;
//		head.next=newNode;
//		length++;
//		
	}
	public void addAfter(AnyType before,AnyType date) {
		Node<AnyType> newNode = new Node<AnyType>(date); 
		tmp = get(before);
		newNode.next = tmp.next;
		newNode.pre = tmp;
		tmp.next.pre = newNode;
		tmp.next = newNode;
		length++;
	}
	/*
	 * 打印方法其实和MyArray一样,两者可以统一写在一个超类里面,用迭代器消除两者的遍历差别,然后打印出
	 * 当前项就可以了,有兴趣的可以自己去实现一下.
	 */
	public String toString() {
		StringBuilder strBuilder = new StringBuilder();
		tmp = head;
		
		strBuilder.append("[");
		while(tmp.next != end) {
			strBuilder.append(tmp.next.date+",");
			tmp=tmp.next;
		}
		if(head.next != end) {
			strBuilder.delete(strBuilder.length()-1, strBuilder.length());
		}
		strBuilder.append("]");
		return strBuilder.toString();
	}
	public Iterator<AnyType> iterator(){
		return new MyLinkIterator();
	}
	/*
	 * 这个迭代器默认就这两个方法,MyArray中我多写了一个remove方法,这里没有写,你可以自己写一个
	 * 或者再写一些其他有意思的方法。
	 */
	private class MyLinkIterator implements Iterator<AnyType>{
		public Node<AnyType> tmp_iterator = head;
		@Override
		public boolean hasNext() {
			// TODO Auto-generated method stub
			return tmp_iterator.next != end;
		}

		@Override
		public AnyType next() {
			// TODO Auto-generated method stub
			tmp_iterator = tmp_iterator.next;
			return (AnyType)tmp_iterator.date;
		}
		
	}
	
}

 

同上面一样注释很清晰,实现最基本的方法,当然还有迭代器,为了用foreach的不用foreach不实现迭代器也可以反正toString也没有迭代器去写,这样很不美丽,后面会提到这个问题。

下面开始实现栈:

首先用我们的MyArray实现。

package dome.gaoxiaoming;
/*
 * 栈这个东西老是在头上操作来操作去的,但在链表和数组表(好吧都是表),在表看来就是在他们屁果后面动手动脚的
 * 一直在屁果后面那么链表的插入优势就没有了,当链表没有优势的时候那么数组就会快一点,因为数组是最基本的数据结构
 * 直接面向内存他的处理cup指令应该是基本的很快的,而链表节点是对象,靠地址查找,被分在层次更高的堆上,当
 * 插入和删除的优势没有了,慢一点也很正常,不过链表可以自由扩容只要内存够大不像数组扩容还要从新复制自己。
 * 最后如果一个数据结构老是从头或屁果操作的话像栈和队列,那么链表的优势就受限了,照这个理论的话,栈和队列用数组
 * 实现效率会相对高一点。现实中栈和队列应该就是用数组实现的,我不确定,懂操作系统出来留个言说明一下。当然链表
 * 的运用也很广阔像用来实现树什么的灵活使用都会一样强大。
 * 
 */
public class MyArrayStack<AnyType> {
	private MyArray<AnyType> stack = new MyArray<AnyType>();
	public void push(AnyType date) {
		stack.add(date);
	}
	/*
	 * 这里的peek情况和MyLinkStack一样不是很美丽,原因就不再赘述了。
	 */
	public AnyType peek() {
		return stack.get(stack.getDate(stack.getSize()));
	}
	/*
	 * 这个pop弹栈函数也没有,写空栈的情况,那么空栈下会不会像MyLinkStack一样完蛋到程序直接挂掉了
	 * 如果又挂掉岂不是太惨了,所以我去MyArray里看了一下看我的remove里面写的是什么东西,结果发现了一句话
	 * 	if(index>=size || index < 0) {
	 *		return ;
	 *  }
	 *  size是元素个数,index是索引 index的范围是0到size-1。所以当index大于或等于size都是非法操作。
	 *  当size = 0 也就是栈为空时index = -1 ,所有小于零的都是非法,所以我没想到我在remove里竟然做了
	 *  边界的检查,所以这里再弹空栈程序也不会挂掉。可喜可贺。
	 */
	public void pop() {
		stack.remove(stack.getSize()-1);
	}
	public String toString() {
		return stack.toString();
	}
}

还行,不是太好,不过该有的都差不多。

下面用我蒙的双向MyLink链表实现栈。

package dome.gaoxiaoming;


import dome.gaoxiaoming.MyLink;
public class MyLinkStack<AnyType> {
	private MyLink<AnyType> stack = new MyLink<AnyType>();  
	public void push(AnyType date) {
		stack.add(date);
	}
	public AnyType peek() {
		return stack.getDate(stack.get_cursor());
	}
	
	/*
	 * pop()这一部分实现的不是很美丽,而且没有返回值,一般的pop()都会返回出栈后的对象
	 * 因为我的链表是出于实用角度出发的所以remove方法不是靠对象或者索引去删除对象的
	 * 在现实中谁会记住对象或者是索引什么,只会记住自己存了什么值,比如老师存学生的学号,如果老师要删除一个学号
	 * 他不可能记住这个学号是那个对象这个对象的排在第几位,他只知道学号所以我的remove()方法只接受一个用户知道
	 * 的要删除的值,这在内部可能会变得不美丽,因为在内部你很容易得到对象,但得到对象之后我的remove方法删不掉
	 * 它,还要通过getDate方法再去得到对象存的值,然后再去删除它,当然直接写一个接受对象并删除的方法很简单
	 * 内部可以变得很美丽,但是用户不知道对象,
	 * (用户也拿不到当前对象或对象的引用,因为Node是私有的。这个安全
	 * 什么的会带来很多问题,还有泛型,明明到最后都是Object类型还非要转来转去的,用泛型最后搞得乱七八糟的不如
	 * 直接都用Object,但都用Object的话语义又很模糊,到最后你自己都不知道这个Object到底是什么鬼东西
	 * 这是题外话了)
	 * 什么乱七八糟的,所以你要接受他传的数据,然后再找到这个对象,然后删除
	 * 所以,我是按照我的想法来做的,跟其他的不一样很正常,你也可以自己做一个删除方法,不管你是怎么删除的都是你的
	 * 思想和方法,没有什么对错,只是角度不同罢了。
	 */
	public void pop(){
		stack.remvoe(stack.getDate(stack.get_cursor()));
	}
	public boolean empty() {
		return stack.empty();
	}
	/*
	 * 这个toString真算是投机倒把,直接用了MyLink的toString,不过还好我的链表特意用的是顺序插入
	 * 这样不用改,也不用多加什么方法直接就可以实现栈了,不过通篇的表和栈包括队列我都很少作非法输入检查,
	 * 所以你弹出空栈的话天知道会发生什么,不过就当前来说的话,你pop空栈那么cursor会指向head的前一个
	 * head前一个是null 在MyLink 的初始化方法里我令head的pre等于null所以:cursor会等于null然后
	 * remove会尝试删除head,你会发现程序应该直接就挂了,当然在pop里加一句话就可以了
	 * if(empty()){
	 * 		return;
	 * }
	 * 空链表直接返回不操作,当然你也可以扔一个错误,但做程序本来最讨厌的就是错误你还要扔一个,你自己看着办吧。
	 * 别怪我没提醒你
	 */
	public String toString() {
		return stack.toString();
	}
}

还好,注释把该说的都说了,不该说的也扯了一大堆。

下面开始用MyArray实现队列。

package dome.gaoxiaoming;

import static dome.gaoxiaoming.Tool.*;

import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Iterator;
/*
 *这是个实现,挺好,但是很操蛋,我本来打算和链表一样用以前的MyArray表去实现队列,这样当然可以但是会很浪费空间
 *因为队列会无限的添加删除只是在头部删除,添加还是在尾部添加,所以队列最后用一个循环的数组去实现。
 *我重建了一个循环数组去实现,但后来发现要重写一个toString然后我又重写了一个toString方法我打算用以前链表的
 *toString方法,发现很难受,第一我需要一个链表对象,然后把现有的队列添加到链表对象里,然后再调用链表对象,
 *结果数组是循环数组,添加到链表再打印其复杂度还不如再写一个toString方法,结果我就重写了,到现在我已经从写了三个
 *互不兼容,完全不一样的toString方法,这样很不美丽,很操蛋,这个错误是在一开始就设计失误了,我没有想到,后来
 *还要用以前的表去实现栈和队列。这个问题的解决方法就是JDK所做的,JDK把所有toString方法都写在了
 * 抽象类里,然后让表去继承它,绝妙的是就是他用迭代器去遍历表,然后在打印,我前面好像说过用迭代器去消除
 * 各类的差异性,让遍历统一起来,这样打印一个toString方法搞定。
 * 但事以至此我这个小范围的数据结构就没有必要都实现迭代器JDK的toString源码如下:
 * 它写在 java.util.AbstractCollection<E> 的抽象类下
 * 
 *     public String toString() {
        Iterator<E> it = iterator();
        if (! it.hasNext())
            return "[]";

        StringBuilder sb = new StringBuilder();
        sb.append('[');
        for (;;) {
            E e = it.next();
            sb.append(e == this ? "(this Collection)" : e);
            if (! it.hasNext())
                return sb.append(']').toString();
            sb.append(',').append(' ');
        }
    }

    这个没什么好说的我的toString方法用的是 付远 的思想,从全局出发省略了if语句。
    sb.append(e == this ? "(this Collection)" : e); 这句话很有意思,如果你迭代的对象是当前对象的话
    他会打印出(this Collection),这是jdk1.8的源码,我用了几行很操蛋的代码打印出了这个(this Collection)
    	AbstractCollection asc = new ArrayList();
		asc.add(asc);
		println(asc);
		
    
 */
public class MyArrayQueue<AnyType> {
	private AnyType[] queue ;
	private int front,rear,length,capacity;
	private static int DEFAULT_CAPACITY=10;
	
	public MyArrayQueue() {
		initialzation(DEFAULT_CAPACITY);
	}
	public MyArrayQueue(int capacity) {
		initialzation(capacity);
	}
	@SuppressWarnings("unchecked")
	public void initialzation(int capacity) {
		front = 0;
		rear = 0;
		length=0;
		this.capacity = capacity;
		queue = (AnyType[]) new Object[capacity]; // 泛型真是让人乱七八糟不知所云。	
	}
	public void enqueue(AnyType date) {

		rear = rear % capacity;
		if(length != 0 && rear == front ) {
			return;
		}
		queue[rear] = date;
		rear++;
		length++;
	}
	public void dequeue() {
		front = front%capacity;
		if(length == 0) {
			return;
		}
		front++;
		length--;
	}
	public AnyType peek() {
		if(length==0) {
			return null;
		}
		return queue[front%capacity];
	}
	
	public String toString() {
		StringBuilder std = new StringBuilder();
		std.append("[");
		int tmp=front;
		for(int i =0;i<length;i++) {
			tmp = tmp % capacity;
			std.append(queue[tmp]+",");
			tmp++;
		}
		if(length != 0) {
			std.delete(std.length()-1,std.length());//去掉最后多余的逗号
		}
		std.append("]");
		return std.toString();
	}
	/*
	 *下面是toString的挣扎,正确工作的代码不是一下就写出来的,源于反复的失败。
	 */
//	public String toString() {
//		int tmp = front;
//		while (tmp != rear) {
//			my_link.add(queue[tmp]);
//			tmp++;
//			if(tmp == capacity) {
//				tmp=0;
//			}
//		}
//		my_link.add(queue[rear]);
//		return my_link.toString();
//	}
//	public void rear_add() {
//		rear++;
//		if(rear == capacity) {
//			rear=0;
//		}
//		println(rear);
//		println(capacity);
//	}
//	public void front_add() {
//		front++;
//		if(front == capacity) {
//			front=0;
//		}
//	}
	
}

这个实现可以用惨烈来形容,首先没有我们的MyArray,其次在toString上吃了亏。

下面有MyLink链表实现队列。

package dome.gaoxiaoming;
/*
 * jdk提供了横多队列的实现,有的可以阻塞线程,有的空间是无限的只要你内存够大,有的最大值是Integer的最大值
 * 也就是Integer.MAX_VALUE;还有流弊一点的提供相应的策略给队列的元素划分权重然后决定优先级。下面是JDK的
 * 几个队列,大家了解一下。
 * 
 * 	ArrayBlockingQueue :一个由数组结构组成的有界阻塞队列。	
	LinkedBlockingQueue :一个由链表结构组成的有界阻塞队列。
	PriorityBlockingQueue :一个支持优先级排序的无界阻塞队列。
	DelayQueue:一个使用优先级队列实现的无界阻塞队列。
	SynchronousQueue:一个不存储元素的阻塞队列。
	LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。
	LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。
	
 */

public class MyLinkQueue<AnyType> {
	private MyLink<AnyType> queue = new MyLink<AnyType>();
	public void enqueue(AnyType date) {
		queue.add(date);
	}
	public AnyType peek() {
		return queue.getDate(queue.get_head());
	}
	/*
	 * 空队列出队还是会挂掉,原因跟栈的一样,我就不多废话了。
	 */
	public void dequeue() {
		queue.remvoe(queue.getDate(queue.get_head()));
	}
	public String toString() {
		return queue.toString();
	}
}

 

这个实现又挽回了一点面子,好了,全篇完结。

csdn被广告蒙蔽了心灵,各位江湖道友各自安好在下告辞另寻发展,青山不到,绿水长流,他日更相会,再谈江湖是非恩怨儿女情愁。

 

 

 

 

 

 

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值