数据结构和算法--链表一之单向链表的简单实现
Posted GoNewLife
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构和算法--链表一之单向链表的简单实现相关的知识,希望对你有一定的参考价值。
链表在我们java中也是一种基础的数据结构,可以理解成是一种和数组同级的数组结构,正如我们所知,在我们使用这集合ArrayList和LinkedList的时候,总会学习底层数组实现的ArrayList和双向链表实现的LinkedList的区别。在这里,我们将要讲说的是单向链表的简单实现,让我们体会一下链表在实现增删改查的时候是怎么样的一个操作,在和前边涉及到的数组的增删改查进行对比,得到我们学习的结论,数组的增删效率低于链表结构,查改效率高于链表结构!
什么叫做单向链表,我们可以理解为一个一个节点链接起来的一条链子,从第一个开始有指向下一个的箭头,也就是说单向链表的每一个节点我们可以理解为是一个对象,里面包含了date内容属性,同时也包含了next下一个对象的属性。代码如下:
public class MyList { // 定义一个头结点 private Node head; // 链表的长度 private int size; // 构造一个节点内部类 class Node { // 节点的存放数据 int date; // 节点的next域 Node next; public Node(int date) { this.date = date; } } /** * 获取链表的长度 * * @return */ public int getSize() { return size; } /** * 根据下标获取对应位置的节点 * * @param index * @return */ public Node getNodeByIndex(int index) { // 判断index的有效性 if (index < 0 || index > getSize() - 1) { return null; } else { // 对链表是否为空进行判断 if (isEmpty()) { return null; } else { Node cur = head; for (int i = 0; i < index - 1; i++) { cur = head.next; head = cur; } return cur; } } } /** * 根据节点内容判断节点是否存在 * * @param date * @return */ public boolean contains(int date) { for (int i = 0; i < getSize(); i++) { if (getNodeByIndex(i).date == date) { return true; } } return false; } /** * 根据节点内容获取节点位置 有返回index,没有返回-1 * * @param date * @return */ public int getNodeByDate(int date) { // 判断节点是否存在 boolean b = contains(date); if (b) { for (int i = 0; i < getSize(); i++) { if (getNodeByDate(date) == date) { return i; } } } return -1; } /** * 判断链表是否为空 * * @return */ public boolean isEmpty() { if (getSize() > 0) { return false; } else { return true; } } /** * 在链表前端插入一个节点 * * @param date */ public void addFirstNode(int date) { // 通过链表是否为空判断是否有头节点 if (isEmpty()) { head = new Node(date); } else { Node node = new Node(date); node.next = head; } } /** * 在链表的末端加入一个节点 * * @param date */ public void addLastNode(int date) { // 获取链表末端的节点 Node node = getNodeByIndex(getSize() - 1); // 得到需要插入的节点 Node nowNode = new Node(date); // 将上一个节点的next指向当前节点 node.next = nowNode; } /** * 在index位置插入节点 * * @param index * @param date */ public void addNodeByIndex(int index, int date) { // 对index进行有效性判断 if (index > getSize() || index < 0) { return; } if (index == 0) { addFirstNode(date); } else if (index == getSize()) { addLastNode(date); } else { // 获取上一个节点 Node node1 = getNodeByIndex(index - 1); // 获取当前插入的节点 Node nowNode = new Node(date); // 获取下一个节点 Node node2 = getNodeByIndex(index + 1); // 与上下节点建立链接 node1.next = nowNode; nowNode.next = node2; } } /** * 根据index删除对应位置的节点 * * @param index */ public void deleteNode(int index) { // 找到index位置的节点,判断该节点是否为空 if (getNodeByIndex(index) != null) { // 如果是头节点 if (index == 0) { head.next = head; } else if (index == getSize() - 1) { // 获取上一个节点,并将它的next指向空 getNodeByIndex(getSize() - 2).next = null; } else { // 获取上一个节点 Node node1 = getNodeByIndex(index - 1); // 获取下一个节点 Node node2 = getNodeByIndex(index + 1); // 获取当前节点 Node nowNode = getNodeByIndex(index); // 断开当前节点和上下节点的链接 nowNode.next = null; node1.next = node2; } } } /** * 对index位置的Node进行修改 * * @param index * @param date */ public void updateNode(int index, int date) { // 判断该节点是否存在 if (getNodeByIndex(index) != null) { // 获取对应位置的Node Node nowNode = getNodeByIndex(index); // 对它的date进行修改 nowNode.date = date; } } }
在上述代码中就是单向链表的简单实现,总的来说我们需要注意的是在输入数据时候,比如下标,我们需要对下标的合法性就行判断在进行操作,我们应该考虑到多种异常情况,然后也就比较简单了。明天我们将继续讲述关于单向链表的一些简单操作问题,如以下
1、求单链表中节点的个数
2、查找单链表中的倒数第k个结点
3、查找单链表中的中间结点
4、合并两个有序的单链表,合并之后的链表依然有序
5、单链表的反转
6、从尾到头打印单链表
7、判断单链表是否有环
8、取出有环链表中,环的长度
9、单链表中,取出环的起始点
10、判断两个单链表相交的第一个交点
以上是关于数据结构和算法--链表一之单向链表的简单实现的主要内容,如果未能解决你的问题,请参考以下文章