通过学习自定义链表,了解链表的数据结构。
首先写一个链表类 :LinkedList.java
最后,测试: Test.java、
知识点:
1.链表的内部维护了一个节点Node类。该类包括数据域和指针域(指针域指向下一个Node节点)
2.通常需要一个虚拟头结点,但不是必须的。
结构:
LinkedList.java:
package LinkedList;
public class LinkedList <E>{
/**
* 维护的一个内部类,描述节点信息
* @author Xiaohua
*
*/
private class Node{
public E e;//数据域
public Node next;//指针域
public Node(E e, Node next) {
this.e=e;
this.next=next;
}
public Node(E e) {
this(e,null);
}
public Node() {
this(null,null);
}
@Override
public String toString() {
return e.toString();
}
}
private Node dummyHead;//虚拟头结点
private int size;//链表大小
/**
* 无参构造函数,初始化一个虚拟头结点,数据域、指针域都为null。
*/
public LinkedList() {
dummyHead=new Node();
size=0;
}
/**
* 获取链表中元素个数
* @return
*/
public int getSize() {
return size;
}
/**
* 判断链表是否为空
* @return
*/
public boolean isEmpty() {
return size==0;
}
/**
* 在链表的指定位置添加元素
* (不是常用操作,练习用)
* pre的作用:找到要插入索引位置的前一个Node节点
* @param index
* @param e
*/
public void add(int index,E e) {
if(index < 0 || index > size) {
throw new IllegalArgumentException("添加失败,不合法的索引值");
}
Node pre=dummyHead;
for(int i=0;i<index;i++) {
pre=pre.next;
}
Node node=new Node(e);
node.next=pre.next;
pre.next=node;
//以上3句等价于这1句:
//pre.next = new Node(e, pre.next);
size++;
}
/**
* 在链表头部添加元素
* @param e
*/
public void addFirst(E e) {
add(0,e);
}
/**
* 在链表尾部添加元素
* @param e
*/
public void addLast(E e) {
add(size,e);
}
/**
* 获取链表指定索引的元素
* (不是常用操作,练习用)
* cur的作用:代表当前指向的Node节点。
* @param index
* @return
*/
public E get(int index) {
if(index < 0 || index >= size) {
throw new IllegalArgumentException("获取失败,不合格索引。");
}
Node cur=dummyHead.next;
for(int i=0;i<index;i++) {
cur=cur.next;
}
return cur.e;
}
/**
* 获得链表的第一个元素
* @return
*/
public E getFirst() {
return get(0);
}
/**
* 获得链表的最后一个元素
* @return
*/
public E getLast() {
return get(size-1);
}
/**
* 修改链表的指定索引的值。
* (不是常用操作,练习用)
* @param index
* @param e
*/
public void set(int index,E e) {
if(index < 0 || index >= size) {
throw new IllegalArgumentException("设置失败,不合法索引.");
}
Node cur=dummyHead.next;
for(int i=0;i<index;i++) {
cur=cur.next;
}
cur.e=e;
}
/**
* 判断链表中是否含有指定元素。
* @param e
* @return
*/
public boolean contains(E e) {
Node cur=dummyHead.next;
while(cur!=null) {
if(cur.e.equals(e)) {
return true;
}
cur=cur.next;
}
return false;
}
/**
* 删除指定索引位置的元素,并返回。
* (不是常用操作,练习用)
* @param index
* @return
*/
public E remove(int index) {
if(index < 0 || index >= size) {
throw new IllegalArgumentException("删除失败,不合法索引.");
}
Node pre=dummyHead;
for(int i=0;i<index;i++) {
pre=pre.next;
}
Node ret=pre.next;
pre.next=ret.next;
ret.next=null;
size--;
return ret.e;
}
/**
* 从链表中删除第一个元素, 返回删除的元素
* @return
*/
public E removeFirst(){
return remove(0);
}
/**
* 从链表中删除最后一个元素, 返回删除的元素
* @return
*/
public E removeLast(){
return remove(size - 1);
}
/**
* 从链表删除指定元素
* @param e
*/
public void removeElement(E e) {
Node pre=dummyHead;
while(pre.next!=null) {
if(pre.next.e.equals(e)) {
break;
}
pre=pre.next;
}
if(pre.next!=null) {
Node delNode=pre.next;
pre.next=delNode.next;
delNode.next=null;
size--;
}
}
/**
* 重写Object的toString方法
*/
public String toString() {
StringBuilder sb=new StringBuilder();
Node cur=dummyHead.next;
while(cur!=null) {
sb.append(cur+"-->");
cur=cur.next;
}
sb.append("null");
return sb.toString();
}
}
Test.java:
package LinkedList;
public class Test {
public static void main(String[] args) {
LinkedList<Integer> linkedList = new LinkedList<>();
for(int i = 0 ; i < 5 ; i ++){
linkedList.addFirst(i);
System.out.println(linkedList);
}
linkedList.add(2, 666);
System.out.println(linkedList);
linkedList.remove(2);
System.out.println(linkedList);
linkedList.removeFirst();
System.out.println(linkedList);
linkedList.removeLast();
System.out.println(linkedList);
}
}
控制台输出结果;