`
fancyCR7
  • 浏览: 7458 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论
阅读更多


    数据存储共有两种形式,一种是连续的,比如说数组,存储时是连续的;还有一种是离散的,这就是链表。
链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的引用域。 链表又分为单链表,双链表和循环链表。

我们先来看单链表,图示为:



 

 

 

由图我们可以看出结点左端的方格是数据域,用来存储数据,而右端是引用域,用来存储下一个节点的地址,便于我们方便的读取到。单链表的引用域是单一指向的,指向他的下一个结点。第一个结点称之为根节点,最后一个节点称之为尾结点。

循环链表是与单链表一样,是一种链式的存储结构,所不同的是,循环链表的尾结点的引用域是指向该循环链表的根节点,从而构成一个环形的链。

而双链表就比单链表方便很多,因为单链表指向是单向的,而双链表有两个引用域,一个指向前一个结点,另一个指向下一个结点。当然根节点只有指向下一个节点的引用域,而尾结点只有指向前一个的引用域。这样的话查找数据时就有两种方法,一种是从前面开始查找,一种就是从后面开始查找。



 

 

下面附上我写的双链表的代码:

结点类:

 

public class Node {

	private Object obj;// 数据域

	private Node next;// 引用域
	private Node prior;//引用域

	public Node(Object obj) {
		this.obj = obj;
	}

	public Node getPrior() {
		return prior;
	}

	public void setPrior(Node prior) {
		this.prior = prior;
	}

	public Object getObj() {
		return obj;
	}

	public void setObj(Object obj) {
		this.obj = obj;
	}

	public Node getNext() {
		return next;
	}

	public void setNext(Node next) {
		this.next = next;
	}

}

 链表类:

 

public class LinkedList {

	public Node root;// 根节点
	public Node endNode;// 尾节点
	private int size;// 链表大小

	/**
	 * method of add node
	 * 
	 * @param node
	 */
	public void add(Node node) {

		if (size == 0) {
			root = node;
			endNode = node;

		} else {
			endNode.setNext(node);
			node.setPrior(endNode);
			endNode = node;
		}

		size++;
	}

	/**
	 * method of remove node
	 * 
	 * @param node
	 */
	public Object removeNode(int index) {
		Node node = root;
		Node removeNode;

		if (index == 0) {
			removeNode = root;
			root = node.getNext();

		} else {
			for (int i = 0; i < index - 1; i++) {
				node = node.getNext();
			}
			if (index == size - 1) {
				removeNode = node.getNext();
				node.setNext(null);
			} else {
				removeNode = node.getNext();
				Node nextNode = removeNode.getNext();
				node.setNext(nextNode);
				nextNode.setPrior(node);
			}

		}
		size--;
		return removeNode;
	}

	/**
	 * 按正序查找指定索引位置的值
	 * 
	 * @param index
	 * @return
	 */
	public Object get(int index) {

		if (index < 0 || index >= size) {
			return null;
		} else {

			Node node = root;

			for (int i = 0; i < index; i++) {
				node = node.getNext();

			}

			return node.getObj();
		}

	}

	/**
	 * 按倒序查找指定索引位置的值
	 * 
	 * @param index
	 * @return
	 */
	public Object getReverse(int index) {

		if (index < 0 || index >= size) {
			return null;
		} else {

			Node node = endNode;

			for (int i = size - 1; i > index; i--) {
				node = node.getPrior();
			}
			return node.getObj();
		}
	}

	/**
	 * 返回链表大小的方法
	 * 
	 * @return
	 */
	public int size() {
		return size;
	}

	/**
	 * 得到指定索引位置节点的方法
	 * 
	 * @param index
	 * @return
	 */
	public Node getNode(int index) {
		if (index < 0 || index >= size) {
			return null;
		} else {
			Node node = root;
			for (int i = 0; i < index; i++) {
				node = node.getNext();
			}
			return node;
		}
	}
}

 

 当然,链表的排序也和数组不一样,链表排序时只需改变引用域的指向,但是涉及根节点和尾结点时,要变更根结点和尾结点(将新结点设置为根结点或尾结点)。下面附上双链表的直接插入排序:

 

 

 

 

/**
 * 创建InsertSort类   内置直接插入排链表顺序的方法  按正序排列
 * @author Administrator
 *
 */
public class InsertSort  {

	/**
	 * 对链表排序的方法   直接插入排序
	 * @param list
	 */
	public void InsertSort(LinkedList list) {
		int i, j;
		for (i = 0; i < list.size(); i++) {
			Node temp = list.getNode(i);
			
			for (j = i; j > 0   
					&& Double.parseDouble(temp.getObj().toString()) < Double//将链表节点所存的object型数据转换为double型 便于比较
							.parseDouble(list.getNode(j - 1).getObj()
									.toString()); j--) {
				if (j == 1) {//排前两个的顺序 
					             //当根节点数据大于它下一个节点的的数据的时候 
					             //改变这两个节点的指针指向 并将第二个节点设置为根节点
					Node node1 = list.getNode(j - 1);
					Node node2 = node1.getNext();
					Node node3 = node2.getNext();

					node2.setNext(node1);
					node1.setPrior(node2);
					node1.setNext(node3);
					node3.setPrior(node1);

					list.root = node2;
				} else if (j == list.size() - 1) {//排序最后两个节点数据  同样是改变指针指向
					Node node1 = list.getNode(j - 1);
					Node node2 = node1.getNext();
					Node node3 = node1.getPrior();

					node3.setNext(node2);
					node2.setPrior(node3);
					node2.setNext(node1);
					node1.setPrior(node2);

					list.endNode = node1;

				} else {//排序中间节点数据的方法 改变节点指针指向即可
					Node node1 = list.getNode(j - 1);
					Node node2 = node1.getNext();
					Node node3 = node2.getNext();
					Node node4 = node1.getPrior();

					node4.setNext(node2);
					node2.setPrior(node4);
					node2.setNext(node1);
					node1.setPrior(node2);
					node1.setNext(node3);
					node3.setPrior(node1);
				}
			}

		}

	}

}

 

 

 

备注:图片来自于360百科

  • 大小: 14.6 KB
  • 大小: 12.5 KB
分享到:
评论

相关推荐

    C语言 链表使用示例

    本教程将通过两个经典示例深入讲解如何在C语言中使用链表。 首先,我们来看第一个示例——"Demo1.c"。在这个示例中,我们将创建一个表示学生成绩的链表,每个节点包含学生的ID和分数。为了实现这个链表,我们需要...

    c++链表使用教程

    总结来说,这个C++链表教程涵盖了链表的基本概念、数据结构定义、操作符重载以及常见的链表操作函数实现,这些都是理解和使用链表的关键知识。通过这些内容,开发者可以有效地在C++中构建和管理链表数据结构,进行...

    双向链表使用说明.txt

    双向链表使用说明.txt

    使用 python3 实现一个链表

    使用 python3 实现一个链表 使用 python3 实现一个链表 使用 python3 实现一个链表 使用 python3 实现一个链表 使用 python3 实现一个链表 使用 python3 实现一个链表 使用 python3 实现一个链表 使用 python3 实现...

    数据结构_链表使用的例子程序

    数据结构学习辅助,链表使用例程,注释非常清楚,而且可以实际运行,方便初学者调试、体会

    linux内核链表提取与使用

    将linux内核源码中list.h拿出来, 增删与遍历部分写了详细注释, 关于链表合并, 没用过所以没写. 源码版本是2.6.32, 不过链表的源码改动应该不是很大. 我的邮箱2253238252@qq.com, 代码有什么不对的欢迎发邮件给我

    双向循环链表使用实例.doc

    在本文中,我们将深入探讨如何使用C++实现双向循环链表。双向循环链表是一种特殊的数据结构,每个节点不仅包含数据,还包含两个指针,分别指向前一个节点和后一个节点,形成一个首尾相接的循环链。这种数据结构在...

    集合(链表和数组的区别) 数组和链表.pdf

    链表使用引用来定位元素,时间复杂度为O(n)。这也就是为什么数组的访问速度比链表快的原因。 5. 插入和删除操作 数组插入或删除元素的时间复杂度为O(n),因为需要移动所有元素的位置。链表插入或删除元素的时间...

    python的链表与数组对比,优势和劣势 数组和链表.pdf

    链表使用指针来指向下一个节点,这可以导致指针的使用不当。 ### 实现的复杂性 链表的实现可以很复杂,需要考虑节点的管理、内存的分配等问题。 数组与链表的对比 ------------------- 数组和链表是两种常用的...

    c++链表学习实例--图书管理

    3. 节点号排序:这通常涉及到对链表的遍历,可以使用各种排序算法,如冒泡排序、选择排序或更高效的快速排序、归并排序等。在这个实例中,可能根据图书的编号进行排序。 4. 节点搜索:查找链表中特定值的节点,通常...

    linux内核链表介绍与了解

    这些扩展都是基于基础的`list`结构,增加了链表使用的灵活性和效率。 在实际应用中,比如在网络过滤框架Netfilter中,使用链表来组织协议族的`nf_sockopt_ops`结构,每个结构都有一个`struct list_head list`成员,...

    数据结构——链表——多项式加减

    - **链表的动态内存管理**:链表使用`malloc`动态分配内存,当链表不再需要时,应使用`free`释放已分配的内存,防止内存泄漏。 - **异常处理**:在实际编程中,应添加输入验证和错误处理机制,确保输入的有效性和...

    人工智能-项目实践-信息管理系统-学生信息管理系统之链表的使用

    在实际开发中,为了提高效率,可以考虑使用哈希表或二叉搜索树等数据结构配合链表使用。例如,可以建立一个哈希表,键为学号,值为指向链表中对应节点的指针,这样可以在常数时间内完成查找和删除操作。 链表在人工...

    c静态链表和动态链表

    动态链表使用完毕后,需要释放每个节点占用的内存空间,避免内存泄漏。 ```c void freeList(struct Car *head) { struct Car *p = head; while (p != NULL) { struct Car *temp = p; p = p-&gt;next; free...

    数组和链表的使用场景 数组和链表.pdf

    数组和链表的使用场景 在计算机科学中,数组和链表是两种基本的数据结构,它们都是线性表的实现方式,但它们有着不同的存储结构和访问方式,从而导致不同的使用场景。 数组是一种连续存储的数据结构,即在内存中...

    使用程序设计建立链表信息管理

    在这个课程设计中,我们将探讨如何使用链表来实现信息管理,包括增加、删除和显示链表中的节点。 链表的基本概念: 链表不同于数组,它不是在内存中连续分配空间,而是由一系列分散的节点组成,每个节点包含数据和...

    c语言中链表的使用

    链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:...

    链表的使用,适合初学者学习

    对于初学者来说,这是一份很好的学习资料,能够帮助他们理解链表的工作原理,以及如何在实际编程中使用链表。通过阅读和分析代码,可以加深对链表数据结构的理解,并掌握其在不同场景下的应用。同时,还可以学习如何...

    链表类,对链表操作的封装,使用了类模版

    封装了链表的操作,功能有链表的创建,节点的添加(附加),插入(前插、后插和插入到链表头部),删除,得到节点数据,得到节点位置,得到节点总数,释放链表。 使用了类模版,使得可以让节点中的数据为任意类型,...

Global site tag (gtag.js) - Google Analytics