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