之前就学过数据结构这门课,当时有用c/c++实现过线性表的顺序存储、单链表、双向链表、顺序栈、链栈、图等数据结构;学了java也有一段时间了,最近一直在为投简历求值而努力着,想着对于大公司来说,对于本科生的要求基本上都要熟悉或者掌握常用的数据结构以及算法,所以准备着重新用java实现一遍以前学过的、现在也很常用或者很常考的一些数据结构以及算法。如果大家在阅读的时候发现有什么不合理的地方,还请大家指正!
双向链表的java实现
要求:
* 1.使用内部类,内部类用来存放一个结点的数据,内部类设为私有的;
* 2.内部类要求有一个data变量,用来存储数据,和一个指向下一个结点的结点变量Next,以及一个指向前一个结点的结点变量 prev;并提供诺干结点的构造函数;
* 3.设置三个变量,size:用来存储数组中元素的个数,header用来存储头结点,tail用来存储尾结点;
* 4.具备多个构造函数,一个初始化默认构造;另一个可以指定结点的构造;
* 5.提供如下几个功能:
* a.获取双向链表的大小(size)
* b.根据索引返回元素
* c.根据元素查找在双向链表中出现的第一个位置
* d.向双向链表中的指定位置插入元素
* e.在双向链表的末端添加一个元素
* f.删除指定索引出的元素
* g.删除最后一个元素
* h.判断双向链表是否为空
* i.清空双向链表
java代码实现如下:
public class DoubleLinkedList<T> {
/*
* 用Java实现双向链表
* 用一个内部类存储结点,data存储数据,next存储下一个结点,prev存储上一个结点
* */
private class Node{
private T data;
private Node next;
private Node prev;
@SuppressWarnings("unused")
public Node(){
}
public Node(T data,Node next,Node prev){
this.data=data;
this.next=next;
this.prev=prev;
}
}
//size用来存放链表中的元素个数,header和tail分别用来指向头结点和尾结点
private int size=0;
private Node header;
private Node tail;
//提供两个构造函数,这里可以根据个人需要来
public DoubleLinkedList(){
header=null;
tail=null;
}
public DoubleLinkedList(T data){
header=new Node(data,null,null);
tail=header;
size++;
}
//返回链表的元素个数
public int size(){
return this.size;
}
//判断链表是否为空
public boolean isEmpty(){
return size==0;
}
//根据索引返回元素
public T get(int index){
return getNodeByIndex(index).data;
}
private Node getNodeByIndex(int index){
if(index<0||index>size-1){
throw new IndexOutOfBoundsException("索引值超出链表的边界值");
}
Node current=header;
for(int i=0;i<size&¤t!=null;i++){
if(index==i){
return current;
}
current=current.next;
}
//这一步不出意外的话是走不到的,因为前面两种情况必有一种被执行
return null;
}
//判断元素在链表中出现的第一个位置
public int indexOf(T data){
Node current=header;
for(int i=0;i<size&¤t!=null;i++){
if(current.data.equals(data)){
return i;
}
current=current.next;
}
return -1;
}
//默认是在尾结点后添加
public void add(T data){
if(header==null){
header=new Node(data,null,null);
tail=header;
size++;
}else{
Node node=new Node(data,null,null);
Node before=getNodeByIndex(size-1);
before.next=node;
node.prev=before;
size++;
}
}
//在指定的位置添加一个元素
public void insert(int index,T data){
if(index<0||index>size){
throw new IndexOutOfBoundsException("索引值超出链表的边界值");
}
if(header==null){//判断链表是否为空,这一步很重要,没有这一步有些新增操作会报错。
add(data);
}else{
if(index==0){//index=0表明在头结点进行插入
Node node=new Node(data,null,null);
node.next=header;
header.prev=node;
header=node;
size++;
}else{
Node node=new Node(data,null,null);
Node before=getNodeByIndex(index-1);
node.next=before.next;
node.prev=before;
before.next=node;
size++;
}
}
}
//根据索引删除指定元素
public T delete(int index){
if(index<0||index>size-1){
throw new IndexOutOfBoundsException("索引值超出链表的边界值");
}
Node del=null;
if(index==0){
del=header;
header=header.next;
del.next=null;
header.prev=null;
}else{
del=getNodeByIndex(index);
Node before=getNodeByIndex(index-1);
//判断一下,如果删除的不是最后一个元素,那么直接将下一个元素的prev指向before
if(del.next!=null){
del.next.prev=before;
}else{//否则表示删除的是最后一个元素,那么应该改变tail的位置,这时候before的next也指向空
tail=before;
}
before.next=del.next;
del.next=null;
del.prev=null;
}
size--;
return del.data;
}
//移除最后一个元素
public T remove(){
return this.delete(size-1);
}
//清空链表
public void clear(){
header=null;
tail=null;
size=0;
}
public String toString(){
if(size==0){
return "[]";
}else{
String s="[";
Node current=header;
for(int i=0;i<size&¤t!=null;i++){
if(i<size-1){
s+=current.data+",";
}else{
s+=current.data+"]";
}
current=current.next;
}
return s;
}
}
}
接下来是顺序栈,加油!