`

JAVA数据结构之链表

 
阅读更多

链表:单链表,双链表,循环链表

 

单链表:每个节点有一个内容和一个地址,这个地址指向下一个节点。

第一个加入链表的节点为头结点,它的地址指向第二个节点,第二个节点地址指向第三个节点。。。最后一个节点的地址指向null。

如图所示:



 

 

由这样的关系,我们容易得知只要知道first,我们就可以用first.next.next.....取到每一个节点元素。

对于单链表,我们要实现他的创建,添加,插入,删除,查询(遍历)等方法。

下面的程序只实现了基本的创建与遍历。其余均在双链表会实现。方法类似。

Node.java

package 单链表LinkedList的实现;

/**
 * 节点 包括 内容,地址
 * 
 * @author Huangbin
 *
 */
public class Node<E> {

	E elem;// 节点中的内容

	Node<E> next;// 对下一个节点的引用(下个节点也是Node类型的)

	public Node(E elem) {
		this.elem = elem;
	}

	public String toString() {
		return (String) elem;
	}
}

LinkList.java

package 单链表LinkedList的实现;

public class LinkList {

	public static void main(String[] args) {
		LinkList list = new LinkList();
		Node<String> node = list.creat();
		list.print2(node);
	}

	public Node<String> creat() {
		Node<String> node = new Node<String>("1");
		Node<String> node2 = new Node<String>("2");
		Node<String> node3 = new Node<String>("3");
		Node<String> node4 = new Node<String>("4");

		node.next = node2;
		node2.next = node3;
		node3.next = node4;

		return node;
	}

	/**
	 * 用循环遍历
	 * 
	 * @param head
	 */
	public void print(Node head) {
		Node node = head;
		while (node != null) {
			System.out.println(node);
			node = node.next;
		}
	}

	/**
	 * 用递归遍历
	 * 
	 * @param head
	 */
	public void print2(Node head) {
		if (head != null) {
			System.out.println(head);
			print2(head.next);// 递归 调用本身
		}
	}
}


运行结果:
1
2
3
4

 

双链表:

每个节点包含三部分,指向前一个元素的地址,内容,指向后一个元素的地址。每两个节点都会互相指向对方,一般习惯把第一个加进链表的节点成为头节点。最后一个为尾节点

关系如图所示



 

双链表的插入说明:(删除类似)


 

 

 

在双链表中,实现了一些常用的方法。具体见代码:

package 双链表LinkedList的实现;

import java.util.NoSuchElementException;

/**
 * 双链表
 * @author Huangbin 
 * d2014年7月17日
 * @param <E>
 */
public class LinkList<E> {

	Node<E> first;
	Node<E> last;
	private int length = 0;
	static LinkList list;

	public static void main(String[] args) {
		long t1 = System.currentTimeMillis();
		list = new LinkList<String>();
		list.test();
		long t2 = System.currentTimeMillis();
		System.out.println(t2 - t1);
	}

	public void test() {

		Node<Integer> node = new Node<Integer>(1);
		Node<Character> node2 = new Node<Character>('a');
		Node<Double> node3 = new Node<Double>(3.01);
		Node<Float> node4 = new Node<Float>(0.11f);// 8有效数字
		Node<Byte> node5 = new Node<Byte>((byte) 5);
		Node<String> node6 = new Node<String>("字符串6");
		Node<Boolean> node7 = new Node<Boolean>(true);
		Node<Boolean> node8 = new Node<Boolean>(false);
		Node<Boolean> node9 = new Node<Boolean>(false);
		Object arr[];
		list.add(node);
		list.add(node2);
		list.add(node3);
		list.add(node4, 3);
		list.add(node5);
		list.add(node6);
		list.add(node7);
		list.removeLast();
		list.printHead(first);
		arr = list.toArray();
		for (int i = 0; i < length; i++) {
			System.out.println(arr[i]);
		}
		System.out.println("Size: " + length);
	}

	public void printHead(Node<E> first) {
		if (first != null) {// 存在元素
			System.out.print(first.front);
			System.out.print("\t" + first);
			System.out.println("\t" + first.next);
			printHead(first.next);// 递归 调用本身
		}
	}

	/**
	 * 添加元素
	 * 
	 * @param node
	 */
	public void add(Node<E> node) {
		if (first != null) {// 已经存在元素了
			node.front = last;
			last.next = node;
		} else {
			// 添加第一个节点 头尾均指向第一个节点
			first = node;
		}
		last = node;// 重新指向最后一个节点
		length++;
	}

	/**
	 * 在指定位置插入新的元素
	 * 
	 * @param node
	 * @param num
	 */
	public void add(Node<E> node, int num) {
		if (num > length || num < 0) {
			throw new IndexOutOfBoundsException("Index: " + num + ", Size: "
					+ length);
		}
		if (num == 0) {
			if (first != null) {
				node.next = first;
				first.front = node;
				first = node;
			} else {
				add(node);// 不存在直接加进去。
			}
		} else if (num == length) {
			add(node);
		} else {

			Node<E> temp = first;
			for (int i = 1; i < num; i++) {
				temp = temp.next;
			}
			// 此时,temp指向了num位置
			node.front = temp;
			node.next = temp.next;
			temp.next.front = node;
			temp.next = node;
		}
	}

	/**
	 * 移除指定元素
	 * 
	 * @param node
	 */
	public Node<E> remove(Node<E> node) {
		// 先判断是否在链表中
		if (this.contains(node)) {
			// 遍历链表找到node元素的front与next改变他们的指向

			if (node.front != null && node.next != null) {// node是中间位置的元素

				node.next.front = node.front;
				node.front.next = node.next;// node前一个元素指向node的下一个元素

			} else if (node.next != null) {// 被移除的是第一个元素,且存在下一个元素
				first = node.next;
				first.front = null;
			} else if (node.front != null) {// 被移除的是最后一个元素,且存在下一个元素
				last = node.front;
				last.next = null;
			} else {// 移除最后一个元素了,node的前后都是空
				last = first = null;// 这个时候全部被移除了
			}
			// 清空node,释放资源
			// node.next = null;
			// node.front = null;
			// node.elem = null;
			length--;
			return node;
		} else {
			try {
				throw new Exception("不存在 \"" + node + "\" 元素!");
			} catch (Exception e) {
				e.printStackTrace();
			}
			return null;
		}
	}

	/**
	 * 移除指定下标的元素
	 * 
	 * @param num
	 */
	public Node<E> remove(int num) {
		if (num >= length || num < 0) {
			throw new IndexOutOfBoundsException("index:" + num + ",size:"
					+ length);
		}
		Node<E> node = first;
		for (int i = 0; i < num; i++) {
			node = node.next;
		}
		remove(node);
		return node;
	}

	/**
	 * 移除函相同内容的第一个指定元素
	 * 
	 * @return
	 */
	public Node<E> remove(Object o) {
		// 先判断是否在链表中
		if (this.contains(o)) {
			return remove((get(indexOf(o))));
		}
		return null;
	}

	/**
	 * 移除第一个元素
	 * 
	 * @return
	 */
	public Node<E> removeFirst() {
		if (first == null)
			throw new NoSuchElementException();
		return remove(first);
	}

	/**
	 * 移除最后一个元素
	 * 
	 * @return
	 */
	public Node<E> removeLast() {
		if (last == null)
			throw new NoSuchElementException();
		return remove(last);
	}

	/**
	 * 修改指定元素的内容
	 * 
	 * @param str
	 * @param num
	 */
	public void set(E o, int num) {
		get(num).elem = o;
	}

	/**
	 * 获得num下标位置的元素
	 * 
	 * @param num
	 * @return
	 */
	public Node<E> get(int num) {
		if (num >= length || num < 0) {
			throw new IndexOutOfBoundsException("Index: " + num + ", Size: "
					+ length);
		}
		Node<E> node = first;
		for (int i = 0; i < num; i++) {
			node = node.next;
		}

		return node;
	}

	/**
	 * 获得第一个元素
	 * 
	 * @return
	 */
	public Node<E> getFirst() {
		return first;
	}

	/**
	 * 获得最后一个元素
	 * 
	 * @return
	 */
	public Node<E> getLast() {
		return last;
	}

	/**
	 * 获得链表的长度
	 * 
	 * @return
	 */
	public int getSize() {
		return length;
	}

	/**
	 * 添加元素到链表头
	 * 
	 * @param node
	 */
	public void addFirst(Node<E> node) {
		add(node, 0);
	}

	/**
	 * 添加元素到链表尾
	 * 
	 * @param node
	 */
	public void addLast(Node<E> node) {
		add(node);
	}

	/**
	 * 查找元素内容o在哪个位置,不存在返回-1
	 * 
	 * @param o
	 * @return
	 */
	public int indexOf(Object o) {
		int index = 0;
		if (o == null) {
			for (Node<E> x = first; x != null; x = x.next) {
				if (x.elem == null || x == null) {
					return index;
				}
				index++;
			}
		} else {
			for (Node<E> x = first; x != null; x = x.next) {
				if (o.equals(x.elem) || o.equals(x)) {
					return index;
				}

				index++;
			}
		}
		return -1;
	}

	/**
	 * 是否有包含内容o的元素
	 * 
	 * @param o
	 * @return
	 */
	public boolean contains(Object o) {
		return indexOf(o) != -1;
	}

	/**
	 * 队列式取出首元素,先进先出
	 * 
	 * @return
	 */
	public Node<E> queuePop() {
		return removeFirst();
	}

	/**
	 * 栈式取出首元素,后进先出
	 * 
	 * @return
	 */
	public Node<E> statckPop() {
		return removeLast();
	}

	/**
	 * 放元素进去
	 * 
	 * @param node
	 */
	public void push(Node<E> node) {
		add(node);
	}

	/**
	 * 复制该链表
	 */
	public LinkList<E> clone() {
		LinkList<E> clone = new LinkList<E>();
		clone.first = clone.last = null;
		clone.length = 0;
		for (Node<E> node = first; node != null; node = node.next) {
			clone.add(node);

		}
		return clone;
	}

	/**
	 * 把链表转为数组
	 * 
	 * @return
	 */
	public Object[] toArray() {
		Object[] o = new Object[length];
		int i = 0;
		for (Node<E> x = first; x != null; x = x.next, i++) {
			o[i] = x.elem;
		}
		return o;
	}

	private class Node<E> {

		E elem;// 节点中的内容

		Node<E> front;// 对上一个节点的引用(上个节点也是Node类型的)
		Node<E> next;// 对下一个节点的引用(下个节点也是Node类型的)

		public Node(E elem) {
			this.elem = elem;
		}

		public String toString() {
			return (String) "" + elem;//便于打印
		}
	}

}
运行结果:
null	1	a
1	a	3.01
a	3.01	0.11
3.01	0.11	5
0.11	5	字符串6
5	字符串6	null
1
a
3.01
0.11
5
字符串6
Size: 6
3

 

  • 大小: 16.6 KB
  • 大小: 16 KB
  • 大小: 16.8 KB
0
0
分享到:
评论

相关推荐

    我自己java数据结构之链表

    总结一下,本主题涵盖了Java中的链表数据结构,包括`LinkedList`和`ArrayList`的实现,以及如何通过`Interface`和`Iterator`进行操作。理解这些概念对于编写高效的Java代码至关重要。通过实践和学习,你可以更好地...

    Java数据结构 线性表,链表,哈希表是常用的数据结构

    Java数据结构 线性表,链表,哈希表是常用的数据结构,在进行Java开发时,JDK已经为我们提供了一系列相应的类来实现基本的数据结构

    Java数据结构之链表、栈、队列、树的实现方法示例

    "Java数据结构之链表、栈、队列、树的实现方法示例" 在计算机科学中,数据结构是一种组织和存储数据的方式,以便实现高效的数据存取和处理。Java数据结构中常用的数据结构有链表、栈、队列、树等,本文将详细介绍...

    java 数据结构 遍历链表程序

    本篇文章将深入讲解Java中链表数据结构的遍历程序,以及如何通过`LinkListFour.java`这个文件来实现链表的遍历。 首先,链表不同于数组,它不连续存储数据,而是通过节点间的引用关系构成。每个节点包含两部分:...

    java 数据结构 链表

    链表是一种基础且重要的数据结构,它在计算机科学和编程,尤其是Java中有着广泛的应用。与数组不同,链表中的元素并不在内存中连续存储,而是通过节点间的引用(或称为指针)来连接。每个节点包含两部分:数据域,...

    数据结构JAVA实现

    在这个名为“数据结构JAVA实现”的压缩包中,我们可以看到作者提供了三种重要的数据结构——链表、有序二叉树和队列的Java代码实现。 首先,让我们详细探讨链表。链表是一种线性数据结构,与数组不同,它不连续存储...

    基于java数据结构链表写的猴子选大王

    《基于Java数据结构链表实现的“猴子选大王”》 在计算机科学中,数据结构是编程的基础,它涉及到如何高效地存储和处理数据。本文将深入探讨一个基于Java数据结构链表实现的经典问题——“猴子选大王”,也称作...

    java 数据结构 双向链表

    这是个java编的双向链表的演示,数据结构是编程中很重要,但很难懂的一部分

    Java数据结构之链表(动力节点之Java学院整理)

    在Java中,我们可以使用类来实现链表的数据结构。 首先,我们来看单链表的一些基本操作: 1. **insertFirst**: 在链表头部插入新节点。这个操作的时间复杂度是O(1),因为只需要改变头节点的引用即可。 ```java ...

    数据结构-链表 JAVA语言实现

    数据结构-链表 JAVA语言实现,包含单向链表、双向链表、循环链表的遍历、删除和插入 详细介绍:http://blog.csdn.net/z740852294/article/details/77369439

    Java语言编写的数据结构-链表实现

    在编程领域,数据结构是构建高效算法的基础,而链表作为一种基本的数据结构,对于理解和掌握高级编程技巧至关重要。本文将详细探讨如何使用Java语言来实现链表,包括顺序表和单链表、双链表。 首先,我们来看顺序表...

    java模拟实现数组链表树图等数据结构

    本项目“java模拟实现数组链表树图等数据结构”旨在帮助初学者通过实际操作来理解这些基本数据结构及其工作原理。 首先,数组是最基础的数据结构,它是一个有序的元素集合,元素可以通过索引来访问。在Java中,数组...

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

    数据结构链表是计算机科学中最为基础和重要的数据结构之一,它的灵活多变使得在数据存储、管理和操作上具有更高的效率。本文将基于Java语言来探讨链表相关程序的实现和特点,以及Java内存分配与回收机制对链表实现的...

    java数据结构之实现双向链表的示例

    在Java中,双向链表是一种重要的数据结构,它允许在链表中的元素之间进行前后双向导航。本示例将详细介绍如何在Java中实现一个简单的双向链表,并提供相关的操作方法。 双向链表由一系列节点组成,每个节点包含三个...

    Java数据结构和算法中文第二版_Java数据结构_

    《Java数据结构和算法中文第二版》是一本深入探讨Java编程中数据结构和算法的书籍。数据结构是计算机科学的基础,它涉及到如何有效地组织和存储数据,以便在各种操作下高效地访问和修改。算法则是解决问题的具体步骤...

    Java常见数据结构面试题(带答案)

    "Java常见数据结构面试题(带答案)" 以下是对Java常见数据结构面试题的...本篇文章主要介绍了Java常见数据结构面试题,涵盖了栈、队列、链表、线性表、树、算法、数据结构等知识点,希望对广大的程序爱好者有所帮助。

    求解约瑟夫环 数据结构循环链表 java求解

    其中,循环链表是一种常用的数据结构,它通过链式存储方式形成一个没有头尾之分的闭合结构,非常适合用来模拟这种环形排列的问题。 循环链表由一系列节点组成,每个节点包含数据和指向下一个节点的指针。在Java中,...

    数据结构链表演示(java swing)

    在本项目中,“数据结构链表演示(java swing)”利用了Java Swing库来创建一个图形用户界面(GUI),直观地展示链表和堆栈的操作。 Java Swing是Java AWT(Abstract Window Toolkit)的一个扩展,提供了丰富的组件...

    java 单链表和双向链表的实现

    本话题主要探讨两种常用的数据结构——单链表和双向链表在Java中的实现,以及相关的操作,如在头部添加节点、在尾部添加节点、遍历、逆置和删除。 首先,我们来理解单链表和双向链表的基本概念。单链表是一种线性...

Global site tag (gtag.js) - Google Analytics