数据结构(java)——单链表、双端链表和双向链表

单链表

    链表大家都很熟悉,链表是由若干个节点串起来的一个结构。类似于火车一样,拥有一个头结点(火车头)之后挂着一个个的节点,每个节点后面跟上另一个节点。每个节点分为两个域,一个数据域,用来存放这个节点的数据,一个是节点域,用来存放下一个节点。

    所以对于单链表,用java实现我们首先创建节点类。

Node类:

//联结点,相当于是车厢
public class Node {
	//数据域
	public long data;
	//节点域
	public Node next;
	
	//默认构造方法
	public Node(long value) {
		this.data = value;
	}
	
	//显示方法
	public void display() {
		System.out.print(data + " ");
	}
}

再实现一些链表的基本操作。

LinkList类:

//链表,相当于火车
public class LinkList {
	//车头,头结点
	private Node first;
	
	public LinkList() {
		first = null;
	}
	
	//插入节点,在头结点之后插入
	public void insertFirst(long value) {
		Node aNode = new Node(value);
		aNode.next = first;
		first = aNode;
	}
	
	//删除头节点
	public Node deleteFirst() {
		Node tmp = first.next;
		first = tmp;
		return tmp;
	}
	
	
	//显示方法
	public void display() {
		Node now = first;
		while(now != null) {
			now.display();
			now = now.next;
		}
		System.out.println();
	}
	
	//查找方法
	public Node find(long value) {
		Node now = first;
		while(now.data != value) {
			if(now.next == null) {
				return null;
			}
			now = now.next;
		}
		return now;
	}
	
	//根据数值删除
	public Node delete(long value) {
		Node now = first;
		Node before = first;
		while(now.data != value) {
			if(now.next == null) {
				return null;
			}
			before = now;
			now = now.next;
		}
		
		if(now == first) {
			first = first.next;
		}
		else {
			before.next = now.next;
		}
		return now;
	}
}

对上面一些基础的方法测试:

public class Test {

	public static void main(String[] args) {


		LinkList ll = new LinkList();
		ll.insertFirst(1);
		ll.insertFirst(2);
		ll.insertFirst(3);
		ll.insertFirst(4);
		ll.insertFirst(5);
		
		ll.display();
//		
//		ll.deleteFirst();
//		ll.display();
		
//		ll.find(2).display();
		
//		Node node = ll.delete(2);
//		ll.display();
	}
}

双端链表

双端链表相比于单链表,其实就是加入了一个尾节点来标识表尾

Node类:

//联结点,相当于是车厢
public class Node {
	
	//数据域
	public long data;
	//节点域(后)
	public Node next;
	
	//默认构造方法
	public Node(long value) {
		this.data = value;
	}
	
	//显示方法
	public void display() {
		System.out.print(data + " ");
	}
}

相比于单链表,双端链表在插入和删除等操作时进行了一点小的修改,体现在吧last移动的处理上

FirstLastLinkList类:

//双端链表
public class FirstLastLinkList {
	//车头,头结点
	private Node first;
	//尾节点
	private Node last;
	
	public FirstLastLinkList() {
		first = null;
		last = null;
	}
	
	//插入节点,在头结点之后插入
	public void insertFirst(long value) {
		Node aNode = new Node(value);
		if (isEmpty()) {
			last = aNode;
		}
		aNode.next = first;
		first = aNode;
	}
	
	//尾节点插入
	public void insertLast(long value) {
		Node aNode = new Node(value);
		if (isEmpty()) {
			first = aNode;
		}
		else {
			last.next = aNode;
		}
		last = aNode;
	}
	
	//删除头节点
	public Node deleteFirst() {
		Node tmp = first;
		if (first.next == null) {
			last = null;
		}
		first = tmp.next;
		return tmp;
	}
	
	//显示方法
	public void display() {
		Node now = first;
		while(now != null) {
			now.display();
			now = now.next;
		}
		System.out.println();
	}
	
	//查找方法
	public Node find(long value) {
		Node now = first;
		while(now.data != value) {
			if(now.next == null) {
				return null;
			}
			now = now.next;
		}
		return now;
	}
	
	//根据数值删除
	public Node delete(long value) {
		Node now = first;
		Node before = first;
		while(now.data != value) {
			if(now.next == null) {
				return null;
			}
			before = now;
			now = now.next;
		}
		
		if(now == first) {
			first = first.next;
		}
		else {
			before.next = now.next;
		}
		return now;
	}
	
	//判断是否为空
	public boolean isEmpty() {
		return first == null;
	}
}

针对双端链表的一点测试(大家可以自己使用测测):

public class Test {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		FirstLastLinkList f1 = new FirstLastLinkList();
//		f1.insertFirst(34);
//		f1.insertFirst(56);
//		f1.insertFirst(67);
//		f1.display();
//		
//		f1.deleteFirst();
//		f1.deleteFirst();
//		f1.display();
		
		f1.insertLast(56);
		f1.insertLast(90);
		f1.insertLast(12);
		f1.display();
		
//		f1.delete(12);
//		f1.display();
		while (!f1.isEmpty()) {
			f1.deleteFirst();
			f1.display();
		}
	}
}

双向链表

为了解决尾删这个问题,引入双向链表,在单链表和双端链表中,如果要进行尾部删除,就要吧表遍历一遍,耗时间耗空间。双向链表的每个节点分为3个域,一个数据域,另外两个节点域,既保存前面的节点的信息也保存后面的节点的信息。可以理解为有2个指针,既有next后指针,又有previous前指针。

Node类:

//联结点,相当于是车厢
public class Node {
	
	//数据域
	public long data;
	//节点域(后)
	public Node next;
	//节点域(前)
	public Node previous;
	
	//默认构造方法
	public Node(long value) {
		this.data = value;
	}
	
	//显示方法
	public void display() {
		System.out.print(data + " ");
	}
}

DoubleLinkList类:

//双向链表

public class DoubleLinkList {
	//车头,头结点
	private Node first;
	//尾节点
	private Node last;
	
	public DoubleLinkList() {
		first = null;
		last = null;
	}
	
	//插入节点,在头结点之后插入
	public void insertFirst(long value) {
		Node aNode = new Node(value);
		
		//为空,设置尾节点为新增加的节点
		if (isEmpty()) {
			last = aNode;
		}
		//链表不为空的时候,把插入前第一个节点的previous指向新节点
		else {
			first.previous = aNode;
		}
		aNode.next = first;
		first = aNode;
	}
	
	//尾节点插入
	public void insertLast(long value) {
		Node aNode = new Node(value);
		if (isEmpty()) {
			first = aNode;
		}
		else {
			last.next = aNode;
			aNode.previous = last;
		}
		last = aNode;
	}
	
	//删除头节点
	public Node deleteFirst() {
		Node tmp = first;
		if (first.next == null) {
			last = null;
		}
		else {
			//这里因为存在双指针,所以需要吧后面节点的指向前面节点的那个指针置空
			first.next.previous = null;
		}
		first = tmp.next;
		return tmp;
	}
	
	//删除尾节点
	public Node deleteLast() {
		Node tmp = last;
		if (first.next == null) {
			first = null;
		}
		else {
			//意思同上
			last.previous.next = null;
		}
		last = last.previous;
		return last;
	}
	
	//显示方法
	public void display() {
		Node now = first;
		while(now != null) {
			now.display();
			now = now.next;
		}
		System.out.println();
	}
	
	//查找方法
	public Node find(long value) {
		Node now = first;
		while(now.data != value) {
			if(now.next == null) {
				return null;
			}
			now = now.next;
		}
		return now;
	}
	
	//根据数值删除
	public Node delete(long value) {
		Node now = first;
		while(now.data != value) {
			if(now.next == null) {
				return null;
			}
			now = now.next;
		}
		
		if(now == first) {
			first = first.next;
		}
		else {
			now.previous.next = now.next;
		}
		return now;
	}
	
	//判断是否为空
	public boolean isEmpty() {
		return first == null;
	}
}

对双向链表的基本功能进行一些测试:

public class TestDoubleLinkList {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		DoubleLinkList dL = new DoubleLinkList();
		dL.insertLast(45);
		dL.insertLast(56);
		dL.insertLast(90);
		dL.display();
		
//		dL.deleteLast();
//		dL.display();
		
		while(!dL.isEmpty()) {
			dL.deleteFirst();
			dL.display();
		}
	}

}

猜你喜欢

转载自blog.csdn.net/likunkun__/article/details/79980448