`
hwfantasy
  • 浏览: 21897 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

java自定义双向链表

阅读更多
  今天学习了链表的相关知识,并在此基础上写了一个自定义的双向结点类和链表类。
  链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的结点之间的引用链接实现的。相比于线性表顺序结构,链表比较方便插入和删除操作。
  数组在定义时是在内存中开辟连续的一块区域,而链表则是不固定的,所以在访问时数组更加高效。但是数组必须在定义时就指定大小,所以很有可能造成内存的浪费。还有数组只需要在栈中分配空间,方便快捷。而链表还需要使用到堆中的空间。
下面是自定义的双向结点类
public class LLNode {

	private Object obj;
	private LLNode child = null;
	private LLNode parent = null;

	/**
	 * 它的构造方法
	 */
	public LLNode(Object obj) {
		this.obj = obj;
	}

	public LLNode getChild() {
		return child;
	}

	public void setChild(LLNode child) {
		this.child = child;
	}

	public LLNode getParent() {
		return parent;
	}

	public void setParent(LLNode parent) {
		this.parent = parent;
	}

	public Object getObj() {
		return obj;
	}

}

下面是自定义的双向链表类
public class LinkList {

	private static LLNode head = null;
	private LLNode tail = null;


	/**
	 * 双向链表的构造方法
	 */
	public LinkList() {

	}

	/**
	 * 重写构造方法,创建链表时传入根结点
	 */
	public LinkList(Object obj) {
		head = new LLNode(obj);
		tail = head;
	}

	/**
	 * 向链表最后添加元素
	 * 
	 * @param obj
	 *            添加的元素
	 */
	public void add(Object obj) {
		LLNode node = new LLNode(obj);
		if (head == null) {
			head = new LLNode(obj);
			tail = head;
		} else {
			tail.setChild(node);
			node.setParent(tail);
			tail = node;
		}
	}

	/**
	 * 重写添加的方法 在指定位置添加
	 * 
	 * @param obj
	 *            添加的元素
	 * @param index
	 *            添加的位置(下标值)
	 */
	public void add(Object obj, int index) {
		LLNode node = new LLNode(obj);
		if (index < 0 || index > size()) {// 如果越界
			throw new RuntimeException("越界!可添加的范围为:0~" + size() + ".");
		} else if (head == null) {// 如果没有开始结点
			head = node;
			tail = head;
		} else if (index == 0) {// 如果插入到链表开头
			node.setChild(head);
			head.setParent(node);
			head = node;
		} else if (index == size()) {// 如果插入到链表结尾
			add(obj);
		} else {
			int i = 0;
			LLNode current = head;
			// 找到位置
			while (i != index) {
				current = current.getChild();
				i++;
			}
			LLNode fNode = current.getParent();
			fNode.setChild(node);
			node.setParent(fNode);
			node.setChild(current);
			current.setParent(node);
		}

	}
	
	/**
	 * 替换指定下标处得元素
	 * @param obj 给予替换的元素
	 * @param index  指定的下标
	 */
	public void set(Object obj, int index){
		LLNode node = new LLNode(obj);
		if (index < 0 || index > size()) {// 如果越界
			throw new RuntimeException("越界!可添加的范围为:0~" + size() + ".");
		} else if (head == null) {// 如果没有开始结点
			System.out.println("没有可以替换的位置,因为它是空链表!");
		} else if (index == 0) {// 如果替换到链表开头
			node.setChild(head.getChild());
			head.getChild().setParent(node);
			head = node;
		} else if (index == size()) {// 如果替换到链表结尾
			node.setParent(tail.getParent());
			tail.getParent().setChild(node);
			tail = node;
		} else {
			int i = 0;
			LLNode current = head;
			// 找到位置
			while (i != index) {
				current = current.getChild();
				i++;
			}
			LLNode pNode = current.getParent();
			LLNode cNode = current.getChild();
			pNode.setChild(node);
			node.setParent(pNode);
			node.setChild(cNode);
			cNode.setParent(node);
		}

	}
	
	/**
	 * 返回此链表中首次出现的指定元素的索引,如果此列表中不包含该元素,则返回 -1
	 * @param obj  指定的元素
	 * @return 返回此列表中首次出现的指定元素的下标值
	 */
	public int indexOf(Object obj){
		LLNode current = head;
			// 找到位置
			int i;
			for(i = 0;i<size();i++){
				if(current.getObj() == obj){
					break;
				}
				if(i==(size()-1)){
					return -1;
				}
				current = current.getChild();
			}
			return i;
	}

	/**
	 * 移除链表中的一个结点
	 * 
	 * @param obj
	 *            移除此元素的节点
	 * @return 返回表示是否移除
	 */
	public boolean remove(Object obj) {
		LLNode current;
		if (head.getObj() == obj) {
			current = head.getChild();
			current.setParent(null);
			head = current;
			return true;
		} else if (tail.getObj() == obj) {
			current = tail.getParent();
			current.setChild(null);
			tail = current;
			return true;
		} else {
			current = head.getChild();
			// 找到位置
			for(int i = 0;i<size();i++){
				if(current.getObj() == obj){
					break;
				}
				if(i==(size()-1)){
					return false;
				}
				current = current.getChild();
			}
			LLNode cnode = current.getChild();
			LLNode pnode = current.getParent();
			pnode.setChild(cnode);
			cnode.setParent(pnode);
			return true;
		}
	}

	/**
	 * 移除链表中的一个元素,并返回它
	 * 
	 * @param index
	 *            指定的下标位置
	 * @return 返回这个指定位置的元素
	 */
	public Object remove(int index) {
		LLNode current ;
		if(size() == 0){
			System.out.println("链表中没有元素,无法移除!");
			return null;
		}else if (index < 0 || index > size()) {// 如果越界
			throw new RuntimeException("越界!可移除的范围为:0~" + size() + ".");
		}else if(index == 0){//如果指定位置在开头
			LLNode temp = head;
			current = head.getChild();
			current.setParent(null);
			head = current;
			return temp.getObj();
		}else if(index == size()){//如果指定位置在结尾
			LLNode temp = tail;
			current = tail.getParent();
			current.setChild(null);
			tail = current;
			return temp.getObj();
		}else{
			current = head;
			int i=0;
			while(i != index){
				i++;
				current = current.getChild();
			}
			LLNode cnode = current.getChild();
			LLNode pnode = current.getParent();
			pnode.setChild(cnode);
			cnode.setParent(pnode);
			return current.getObj();
		}
	}

	/**
	 * 移除链表中所有元素
	 */
	public void removeall() {
		head.setChild(null);
		tail.setParent(null);
		head = null;
		tail = head;
	}

	/**
	 * 判断链表长度的方法
	 * 
	 * @return 返回链表的长度
	 */
	public int size() {
		int i = 0;
		LLNode current = head;
		while (current != null) {
			current = current.getChild();
			i++;
		}
		return i;
	}
	
	/**
	 * 得到指定下标的元素,但不在链表中移除它
	 * @param index 指定的下标位置
	 * @return 返回该元素
	 */
	public Object get(int index){
		if(size() == 0){
			System.out.println("链表中没有元素,无法得到!");
			return null;
		}else if (index < 0 || index > size()) {// 如果越界
			throw new RuntimeException("越界!可得到的范围为:0~" + size() + ".");
		}else{
			LLNode current = head;
			int i=0;
			while(i != index){
				i++;
				current = current.getChild();
			}
			return current.getObj();
		}
		
	}

	/**
	 * 从此结点向下遍历的方法
	 * 
	 * @param node
	 *            给予的起始结点
	 */
	public void printfromHead(LLNode node) {
		if (node == null) {
			System.out.println("链表为空!");
		} else {
			System.out.println(node.getObj());
			if (node.getChild() != null) {
				LLNode current = node.getChild();
				printfromHead(current);
			}
		}
	}

	/**
	 * 从此结点向上遍历的方法
	 * 
	 * @param node
	 *            给予的起始结点
	 */
	public void printfromTail(LLNode node) {
		if (node == null) {
			System.out.println("链表为空!");
		} else {
			System.out.println(node.getObj());
			if (node.getParent() != null) {
				LLNode current = node.getParent();
				printfromTail(current);
			}
		}
	}

	/**
	 * 遍历打印链表的方法
	 * 
	 * @param node
	 *            给予的起始结点
	 */
	public void printList(LLNode node) {
		if (node == null) {
			System.out.println("链表为空!");
		} else {
			// 开始向上遍历
			if (node.getParent() != null) {
				System.out.println("----开始向上遍历----");
				LLNode current = node;
				printfromTail(current);
			} else {
				System.out.println("已是根节点,无法向上遍历");
			}
			// 开始向下遍历
			if (node.getChild() != null) {
				System.out.println("----开始向下遍历----");
				LLNode current = node;
				printfromHead(current);
			} else {
				System.out.println("已是尾节点,无法向下遍历");
			}
		}
	}
}
分享到:
评论

相关推荐

    Java有序非循环双向链表算法实例

    在Java中,双向链表可以使用内置的`java.util.LinkedList`类实现,但要实现有序且非循环的特性,可能需要自定义链表节点类,并添加额外的排序逻辑。例如: ```java class Node { int data; Node prev; Node next...

    Java双向链表的实现

    下面我们将详细讲解如何实现一个自定义的Java双向链表,并参考提供的`LinkNode.java`文件来理解其内部机制。 首先,我们需要定义一个表示链表节点的类`LinkNode`。这个类通常包含三个属性:存储数据的`data`字段、...

    2022年Java语言中链表和双向链表Java教程.docx

    《2022年Java语言中链表和双向链表Java教程》 链表作为一种基础且重要的数据结构,广泛应用于编程领域,特别是在Java语言中。虽然Java不直接提供指针,但通过对象引用,我们可以轻松地实现链表的构建。在Java中,...

    双向链表(java实现)

    在计算机科学中,双向链表是一种特殊的链式数据结构,它允许我们在列表的任一位置高效地进行插入和删除...然而,理解如何自定义实现双向链表有助于深入理解数据结构和算法,对于提升编程技能和解决问题的能力大有裨益。

    数据结构学习笔记-链表中的双向链表(JAVA)

    在Java中实现双向链表,我们可以创建一个名为`Node`的类来表示链表节点,其中包含`data`字段用于存储数据,`prev`字段用于存储前驱节点的引用,`next`字段用于存储后继节点的引用。接下来,我们需要一个`Doubly...

    Java版链表模板类

    `CList2`可能添加了双向链表的功能,每个节点不仅有指向下一个节点的指针,还有指向前一个节点的指针。这允许更灵活的插入和删除操作,同时在遍历时可以从两个方向进行。 8. **JavaScript, C 和 C++ 版本**: ...

    java链表 个人总结

    在Java中,LinkedList的节点类是Node,它包含了三个字段:data(存储数据)、next(指向下一个节点)和prev(在双向链表中指向前一个节点)。当我们使用LinkedList时,可以通过addFirst()、addLast()、add()、remove...

    java版链表实现定时器功能

    7. **优化**:为了提高效率,可以使用双向链表,这样可以从头或尾部方便地添加和删除节点。此外,可以考虑使用优先队列(如Java的`PriorityQueue`),其内部已经实现了最小堆,可以快速找到最近的任务。 在J2ME...

    java 链表,仅供参考

    本篇将深入探讨Java中的链表及其自定义实现,同时也会涉及双向链表和链表堆栈的实现。 首先,让我们了解链表的基本概念。链表由一系列节点组成,每个节点包含两个部分:数据域(存储元素)和指针域(指向下一个节点...

    自定义实现常用数据结构 -java版代码.rar

    本压缩包提供的"自定义实现常用数据结构 - java版代码.rar"聚焦于几个关键的数据结构,包括HashMap、LinkedHashMap以及与之相关的红黑树。下面我们将深入探讨这些核心知识点。 首先,HashMap是Java中最常用的一种...

    Jukebox-using-java:使用java的双向链表数据结构的自动点唱机

    在Java中,我们可以自定义一个`SongNode`类来表示链表中的节点,它包含歌曲信息以及prev和next指针。然后,创建一个`Jukebox`类作为链表的容器,提供插入、删除、查找和播放控制等方法。 1. `SongNode`类:包含歌曲...

    基于Java实现数据结构链表相关程序.zip

    链表分为单向链表和双向链表,其中单向链表只能向前遍历,而双向链表可以向前或向后遍历。 1. **链表的基本操作**: - **创建链表**:首先需要定义一个节点类,包含数据和指向下一个节点的引用。然后创建头节点,...

    用java时间数据结构中链表的实例

    如果链表需要支持双向遍历,可以改用双向链表,并在节点中添加一个指向前一个节点的引用。 总之,这个Java实例展示了如何使用链表数据结构,包括节点的定义、链表的遍历以及基本操作。通过扩展这些基础,可以构建更...

    链表实现的查询功能

    在Java中,链表可以自定义为一个类,包含节点类(Node)和链表类(LinkedList)。节点类可能包含数据字段和指向下一个节点的引用,链表类则包含头部节点和各种操作方法,如insert()、delete()和search()。通过阅读和...

    【最强悍的链表】Linux 内核链表源码

    双向链表的优势在于可以从任一方向遍历,同时支持双向插入和删除操作。 接下来是链表操作的API。Linux内核提供了以下关键函数: 1. `INIT_LIST_HEAD(list)`: 初始化一个空链表。将`list`的`next`和`prev`指针设置...

    数据结构—刘小晶—例2.7-用链表结构写的学生成绩管理系统

    链表可以分为单链表、双向链表和环形链表等类型。 在这个学生成绩管理系统中,我们很可能会使用单链表,因为它的实现相对简单。链表的头节点通常用于指示链表的起始位置,而尾节点则指向null,表示链表的结束。 接...

    doubly-linkList_java_

    在Java中,双向链表的实现通常涉及到自定义一个节点类,该类包含三个属性:数据、指向下一个节点的引用和指向前一个节点的引用。节点类的结构可能如下: ```java public class Node { int data; Node next; Node...

    MaQiaoHashArryListMap:有序双向链表

    在Java编程语言中,"MaQiaoHashArryListMap"是一个自定义的数据结构实现,它结合了数组、链表和哈希表的特点,形成一个有序的双向链表。这个数据结构通常用于提供高效的数据存储和检索服务,尤其是在对元素顺序有...

    数据结构来去除链表中的重复元素-java.zip

    对于无序链表,还可以设计一个自定义的数据结构,例如双向链表,其中每个节点包含一个值和一个计数器。遍历原链表时,遇到相同值的节点就增加计数器,否则插入新的节点。最后返回的链表只保留计数器大于1的节点。...

    Java写的数据结构(堆,栈,单链表,双链表)程序!有详细注释!

    本资源包含四个核心的数据结构实现:堆、栈、单链表和双链表,全部使用 Java 语言编写,并且带有详细的注释,非常适合初学者学习和理解。 首先,让我们逐一探讨这些数据结构及其在Java中的实现: 1. **堆**: 堆...

Global site tag (gtag.js) - Google Analytics