Java 模拟双端链表

双端链表:

双端链表与传统链表非常相似.只是新增了一个属性-即对最后一个链结点的引用rear

这样在链尾插入会变得非常容易,只需改变rear的next为新增的结点即可,而不需要循环搜索到最后一个节点

所以有insertFirst、insertLast

删除链头时,只需要改变引用指向即可;删除链尾时,需要将倒数第二个结点的next置空,

而没有一个引用是指向它的,所以还是需要循环来读取操作

/**
 * 双端链表
 * @author stone
 */
public class TwoEndpointList<T> {
	private Link<T> head;		//首结点
	private Link<T> rear;		//尾部指针

	public TwoEndpointList() {

	}

	public T peekHead() {
		if (head != null) {
			return head.data;
		}
		return null;
	}

	public boolean isEmpty() {
		return head == null;
	}

	public void insertFirst(T data) {// 插入 到 链头
		Link<T> newLink = new Link<T>(data);
		newLink.next = head; //新结点的next指向上一结点
		head = newLink;
	}

	public void insertLast(T data) {//在链尾 插入
		Link<T> newLink = new Link<T>(data);
		if (rear != null) {
			rear.next = newLink;
		} else {
			head = newLink;
			head.next = rear;
		}
		rear = newLink; //下次插入时,从rear处插入

	}

	public T  deleteHead() {//删除 链头
		if (isEmpty()) return null;
		Link<T> temp = head;
		head = head.next; //变更首结点,为下一结点
		if (head != null && head.next == null) {
			rear = head;
		}
		return temp.data;
	}

	public T find(T t) {
		if (isEmpty()) {
			return null;
		}
		Link<T> find = head;
		while (find != null) {
			if (!find.data.equals(t)) {
				find = find.next;
			} else {
				break;
			}
		}
		if (find == null) {
			return null;
		}
		return find.data;
 	}

	public T delete(T t) {
		if (isEmpty()) {
			return null;
		} else {
			if (head.data.equals(t)) {
				Link<T> temp = head;
				head = head.next; //变更首结点,为下一结点
				return temp.data;
			}
		}
		Link<T> p = head;
		Link<T> q = head;
		while (!p.data.equals(t)) {
			if (p.next == null) {//表示到链尾还没找到
				return null;
			} else {
				q = p;
				p = p.next;
			}
		}
		q.next = p.next;
		return p.data;
	}

	public void displayList() {//遍历
		System.out.println("List (head-->last):");
		Link<T> current = head;
		while (current != null) {
			current.displayLink();
			current = current.next;
		}
	}

	public void displayListReverse() {//反序遍历
		if (isEmpty()) {
			return;
		}
		Link<T> p = head, q = head.next, t;
		while (q != null) {//指针反向,遍历的数据顺序向后
			t = q.next; //no3
			if (p == head) {// 当为原来的头时,头的.next应该置空
				p.next = null;
			}
			q.next = p;// no3 -> no1  pointer reverse
			p = q; //start is reverse
			q = t; //no3 start
		}
		//上面循环中的if里,把head.next 置空了, 而当q为null不执行循环时,p就为原来的最且一个数据项,反转后把p赋给head
		head = p;
		displayList();
	}

	class Link<T> {//链结点
		T data;		//数据域
		Link<T> next; //后继指针,结点		链域
		Link(T data) {
			this.data = data;
		}
		void displayLink() {
			System.out.println("the data is " + data.toString());
		}
	}

	public static void main(String[] args) {
		TwoEndpointList<Integer> list = new TwoEndpointList<Integer>();
		list.insertLast(1);
		list.insertFirst(2);
		list.insertLast(3);
		list.insertFirst(4);
		list.insertLast(5);
		list.displayList();

		list.deleteHead();
		list.displayList();

		System.out.println("find:" + list.find(6));
		System.out.println("find:" + list.find(3));

		System.out.println("delete find:" + list.delete(6));
		System.out.println("delete find:" + list.delete(5));
		list.displayList();
		System.out.println("----reverse----");
		list.displayListReverse();
	}
}

打印

List (head-->last):
the data is 4
the data is 2
the data is 1
the data is 3
the data is 5
List (head-->last):
the data is 2
the data is 1
the data is 3
the data is 5
find:null
find:3
delete find:null
delete find:5
List (head-->last):
the data is 2
the data is 1
the data is 3
----reverse----
List (head-->last):
the data is 3
the data is 1
the data is 2
/**
 * 使用链表实现栈
 * @author stone
 *
 */
public class LinkStack<T> {
	private TwoEndpointList<T> datas;

	public LinkStack() {
		datas = new TwoEndpointList<T>();
	}

	// 入栈
	public void push(T data) {
		datas.insertFirst(data);
	}

	// 出栈
	public T pop() {
		return datas.deleteHead();
	}

	// 查看栈顶
	public T peek() {
		return datas.peekHead();
	}

	//栈是否为空
	public boolean isEmpty() {
		return datas.isEmpty();
	}

	public static void main(String[] args) {
		LinkStack<Integer> stack = new LinkStack<Integer>();
		for (int i = 0; i < 5; i++) {
			stack.push(i);
		}
		for (int i = 0; i < 5; i++) {
			Integer peek = stack.peek();
			System.out.println("peek:" + peek);
		}
		for (int i = 0; i < 6; i++) {
			Integer pop = stack.pop();
			System.out.println("pop:" + pop);
		}

		System.out.println("----");
		for (int i = 5; i > 0; i--) {
			stack.push(i);
		}
		for (int i = 5; i > 0; i--) {
			Integer peek = stack.peek();
			System.out.println("peek:" + peek);
		}
		for (int i = 5; i > 0; i--) {
			Integer pop = stack.pop();
			System.out.println("pop:" + pop);
		}
	}
}

打印

peek:4
peek:4
peek:4
peek:4
peek:4
pop:4
pop:3
pop:2
pop:1
pop:0
pop:null
----
peek:1
peek:1
peek:1
peek:1
peek:1
pop:1
pop:2
pop:3
pop:4
pop:5
时间: 2024-10-10 17:29:54

Java 模拟双端链表的相关文章

Java单链表、双端链表、有序链表实现

Java单链表.双端链表.有序链表实现 原创 2014年03月31日 23:45:35 标签: Java / 单链表 / 双端链表 / 有序链表 65040 单链表: insertFirst:在表头插入一个新的链接点,时间复杂度为O(1) deleteFirst:删除表头的链接点,时间复杂度为O(1) 有了这两个方法,就可以用单链表来实现一个栈了,见http://blog.csdn.net/a19881029/article/details/22579759 find:查找包含指定关键字的链接点

Java数据结构——用双端链表实现队列

//================================================= // File Name : LinkQueue_demo //------------------------------------------------------------------------------ // Author : Common //类名:FirstLastList //属性: //方法: class FirstLastList_long{ private Lin

《Java数据结构与算法》笔记-CH5-链表-5用双端链表实现队列

1 //用双端链表实现队列 2 /** 3 * 节点类 4 */ 5 class LinkQ { 6 private long data; 7 public LinkQ next; 8 9 public LinkQ(long d) { 10 this.data = d; 11 } 12 13 public String toString() { 14 return String.valueOf(this.data); 15 } 16 } 17 /** 18 * 双端链表类 19 */ 20 cl

Data Handler 大模拟 + 双端链表 hdu 4268

E - Data Handler Time Limit:10000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Description You are in charge of data in a company, so you are called "Data Handler". Different from the data in computer, the data

JAVA基础——链表结构之双端链表

双端链表:双端链表与传统链表非常相似.只是新增了一个属性-即对最后一个链结点的引用 如上图所示:由于有着对最后一个链结点的直接引用.所以双端链表比传统链表在某些方面要方便.比如在尾部插入一个链结点.双端链表可以进行直接操作 但传统链表只能通过next节点循环找到最后链结点操作.所以双端链表适合制造队列. 下面的双端链表类.有几个重要方法. insertFirst(插入首链结点) 这个方法与上篇博文的单链表是基本一样的.唯一区别就是,多了个last引用的操作.正常由于last是指向尾链结点的引用,

研磨数据结构与算法-02双端链表与双向链表

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 + " "); } } 双端链表: /*

Redis源码-数据结构之Adlist双端链表

Redis的Adlist实现了数据结构中的双端链表,整个结构如下: 链表节点定义: typedef struct listNode { struct listNode *prev; struct listNode *next; void *value; } listNode; 链表定义: typedef struct list { listNode *head; listNode *tail; void *(*dup)(void *ptr); void (*free)(void *ptr); i

双端链表再次实现

package ch05; /** * 1:什么是双端链表. * 链表中保存着对最后一个链结点引用的链表 * 2:从头部进行插入 * 要对链表进行判断,如果为空则设置尾结点为新添加的结点 * 3:从尾部进行插入 * 如果链表为空,则直接设置头结点为新添加的结点 * 否则设置尾结点的后一个结点为新添加的结点 * 4:从头部进行删除 * 判断头结点是否有下一个结点,如果没有 * 则直接设置结点为null. * * */ public class FirstLastLinkList { //头结点 p

双端链表

双端链表 链表作为数组之外的一种常用序列抽象, 是大多数高级语言的基本数据类型, 因为 C 语言本身不支持链表类型, 大部分 C 程序都会自己实现一种链表类型, Redis 也不例外 —— 实现了一个双端链表结构. 双端链表作为一种常见的数据结构, 在大部分的数据结构或者算法书里都有讲解, 因此, 这一章关注的是 Redis 双端链表的具体实现, 以及该实现的 API , 而对于双端链表本身, 以及双端链表所对应的算法, 则不做任何解释. 读者如果有需要的话,可以参考维基百科的双端链表词条,里面