如何创建数组列表
如何创建单链表
1.开始创建单链表
实现我们前面写的接口,使我们的链表更规则化
public class LinkNodes<E> implements List{
private Node head; //头结点
private Node tail; //尾节点,方便快速插入
private int size; //链表元素个数
//构造函数
public LinkNodes(){
this.head = null;
this.tail = null;
this.size = 0;
}
@Override
public void add(Object e) {}
@Override
public Object get(int index) {return null;}
@Override
public void detlete(int index) {}
@Override
public void change(int Index, Object e) {}
private class Node{
private E e;
private Node next;
public Node(E e,Node next){
this.e = e;
this.next = next;
}
public Node(E e){
this(e,null);
}
}
}
2.重写方法
这里我们重写了从list那里继承来的方法
- add(),添加时先判断链表是否为空,为空则新建节点并让尾节点等于头节点,不为空直接让尾节点的next指向新节点就可以了。
- get(int index),我们先写一个getNode()方法找到要找的节点,这也是方便之后的方法进行找节点的操作,首先判断index是否越界,越界则报错,否则通过循环找到我们要找的节点,然后返回要找的节点,get()直接通过getNode()返回节点数据。
- delete(int index),这里我们先看是否是要删除头节点或尾节点,是头的话要把头节点改为原头节点的下一个节点,是尾节点的话要找到尾节点的前一个节点,再将其改为尾节点;不是的话就通过get()方法找到它的前一个节点,然后进行删除操作。
- change(int index, Object e), 直接通过get()找到节点进行修改。
代码如下(示例):
private Node getNode(int index) {
if(index <0 || index > this.size-1) {
throw new IllegalArgumentException("index is error");
}
Node node = this.head;
int i = 0;
while(i < index) {
node = node.next;
i++;
}
return node;
}
@Override
public void add(Object e) {
if(tail == null) {
this.head = new Node(e);
this.tail = head;
}else {
tail.next = new Node(e);
tail = tail.next;
}
size++;
}
public Object get(int index) {
return getNode(index).e;
}
@Override
public void delete(int index) {
if(this.size == 1) {
this.head = null;
this.tail = null;
}else if(index == 0){
this.head = head.next;
}else if(index == this.size - 1) {
this.tail = getNode(index - 1);
tail.next = null;
}else {
Node preNode = getNode(index - 1);
preNode.next = preNode.next.next;
}
this.size--;
}
@Override
public void change(int index, Object e) {
getNode(index).e = e;
}
3.重载方法并添加自定义方法
- 重载add(),我们发现上述的add()只能从尾节点插入,因而我们可以重载add()方法,通过传入一个index让它可以实现中间插入
public void add(Object e, int index) {
Node newNode = new Node(e);
if(index == 0) {
newNode.next = this.head;
this.head = newNode;
}else{
Node preNode = getNode(index-1);
newNode.next = preNode.next;
//preNode的下一个节点指向要插入节点node
preNode.next = newNode;
}
this.size++;
}
- 其他方法
//获取链表长度
public int length(){
return this.size;
}
//打印链表
public void print() {
if(this.head == null) {
System.out.println("This LinkNodes is null");
return;
}
Node temp = this.head;
System.out.print("[");
System.out.print(temp.e);
while(temp.next!= null) {
temp = temp.next;
System.out.print(" -> "+temp.e);
}
System.out.println("]");
}
单链表和数组列表
最后对比一下我们的单链表和数组列表,我们可利用以下代码来输出程序运行的时间,同时为了增加对比性,我们再导入Java里自带的数组列表ArrayList和LinkedList,他们都在java.util这个包下面,且都实现了List这个接口。
long start1 = System.currentTimeMillis();//记录开始时间
dosomethings();
long end1 = System.currentTimeMillis();//记录结束时间
System.out.print("程序运行时间为:"+(end1 - start1)+"ms\n");
直接上我的电脑上的运行结果吧:
添加1000000元素:
LinkNodes添加元素用时:343ms
LinkedList添加元素用时:209ms
MyList添加元素用时:101ms
ArrayList添加元素用时:102ms
删除1000元素
LinkNodes删除元素用时:1ms
LinkedList删除元素用时:0ms
MyList删除元素用时:10110ms
ArrayList删除元素用时:919ms
查找10000元素
LinkNodes找元素用时:118ms
LinkedList找元素用时:168ms
MyList找元素用时:0ms
ArrayList找元素用时:0ms
插入10000元素
LinkNodes插入元素用时:67ms
LinkedList插入元素用时:72ms
MyList插入元素用时:3202ms
ArrayList插入元素用时:2632ms
结果很明显链表删除和插入相当快,而查找元素时就显得慢了,而虽然数组列表插入和删除慢但它获取某个元素很快。而对比也发现Java自带的ArrayList和LinkedList运行起来也比我们自己写的代码快,这也是为什么我们应当多看源码。