LinkedList的手动实现

上一篇我们讲解了Collection接口之List子接口中的ArrayList、Vector以及Stack的实现类,由于比较简单,不在赘述,下来我们讲解List接口之LinkedList实现类

(1)LinkedList类本质上是一个双向链表,也是单向队列,双向队列,栈的实现类;

(2)LinkedList类实现了单向队列,双向队列的接口,自身也提供了栈操作的方法,链表操作的方法;

(3)LinkedList类是线程不安全的,在多线程中要保证线程安全,可使用:

List  list = Collections.synchronizedList(new LinkedList());

(4)无论是链表还是队列,都特别擅长操作头和尾结点;在LinkedList中大多数方法都是

xxFirst()或者xxLast()方法的。

注意:ArrayList、LinkedList、Vector类三者都实现了List接口,共同的特点:记录元素添加顺序而且可以重复出现

接下来我们就手动的实现一个双向链表:

(1)链表中节点的定义:

//链表中的每个结点
	class Node{
		Node prev;	//上一节点对象
		Node next;	//下一节点对象
		Object ele;	//当前节点中储存的数据
		
		public Node(Object ele){
			this.ele = ele;
		}
	}


(2)链表的头插,尾插,删除(删头、删尾、删中间),获取指定key元素的值:

//手动实现 双向链表
public class MyLinkedList {
	
	private Node first;//链表的第一个节点 
	private Node last;//链表的最后一个节点
	private int size = 0;//节点的数量
	
	//根据元素key,获取节点值
	public Node findByKey(Object ele){
		//找到被删除的节点
		Node current = this.first;
		for (int i = 0; i < size; i++) {
			//当前节点值等于参数值
			if(current.ele.equals(ele)){
				break;
			}
			if(current.next == null){
				return null;
			}
			current = current.next;
		}
		return current;
	}
	
	//向链表的头插入节点
	public void addFirst(Object ele) {
		Node node = new Node(ele);	//新创建一个新节点
		
		if(size == 0){
			this.first = node;//当前链表无节点,头和尾都指向当前结点
			this.last = node;
		}else{
			//新增节点的下一节点指向第一个节点
			node.next = this.first;
			//第一个节点的前驱指向新增节点
			this.first.prev = node;
			//头节点前移
			this.first = node;
		}
		size++;
	}
	
	//向链表的尾部添加节点
	public void addLast(Object ele) {
		Node node = new Node(ele);//需要保存一个节点对象
		
		if(size == 0){
			this.first = node;	//当前链表无节点,头和尾都指向当前结点
			this.last = node;
		}else{
			//最后一个节点的后驱指向新增节点
			this.last.next = node;
			//新增节点的前驱指向最后一个节点
			node.prev = this.last;
			//最后节点后移
			this.last = node;
		}
		//节点数增加一
		size++;
	}
	
	//删除指定的元素值
	public void remove(Object ele){
		//找到被删除的节点
		Node current = this.first;
		for (int i = 0; i < size; i++) {
			if(!current.ele.equals(ele)){
				if(current.next == null){
					return;
				}
				current = current.next;
			}
		}

		//删除节点
		if(current == this.first){	//删头
			this.first = current.next;
			this.first.prev = null;
		}else if(current == this.last){//删尾
			this.last = current.prev;
			this.last.next = null;
		}else{//删中间
			current.prev.next = current.next;
			current.next.prev = current.prev;
		}
		size--;	//长度减一
	}
	
	//打印所有节点的元素值
	@Override
	public String toString() {
		if(size == 0){
			return "[]";
		}
		StringBuilder sb = new StringBuilder(size * 2 + 1);
		Node current = this.first;//第一个节点
		sb.append("[");
		for (int i = 0; i < size; i++) {
			sb.append(current.ele);
			if(i != size - 1){
				sb.append(",");
			}else{
				sb.append("]");
			}
			current = current.next;	//获取下一个节点
		}
		return sb.toString();
	}
	
	//链表中的每个结点
	class Node{
		Node prev;	//上一节点对象
		Node next;	//下一节点对象
		Object ele;	//当前节点中储存的数据
		
		public Node(Object ele){
			this.ele = ele;
		}
	}

}


(3)测试代码:

public class MyLinkedListDemo {

	public static void main(String[] args) {
		MyLinkedList list = new MyLinkedList();
		list.addLast("D");
		list.addLast("E");
		list.addLast("F");
		
		list.addFirst("C");
		list.addFirst("B");
		list.addFirst("A");
		
		list.remove("C");
		
		System.out.println(list.toString());
		
		Node keyNode = list.findByKey("D");
		System.out.println(keyNode.ele);
	}
}



猜你喜欢

转载自blog.csdn.net/super_yc/article/details/73467488