数据结构和算法--链表一之单向链表的简单实现

  链表在我们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、判断两个单链表相交的第一个交点

  

时间: 2024-08-14 10:02:11

数据结构和算法--链表一之单向链表的简单实现的相关文章

java数据结构与算法之顺序表与链表深入分析

转载请注明出处(万分感谢!): http://blog.csdn.net/javazejian/article/details/52953190 出自[zejian的博客] 关联文章: java数据结构与算法之顺序表与链表设计与实现分析 java数据结构与算法之双链表设计与实现 ??数据结构与算法这门学科虽然在大学期间就已学习过了,但是到现在确实也忘了不少,因此最近又重新看了本书-<数据结构与算法分析>加上之前看的<java数据结构>也算是对数据结构的进一步深入学习了,于是也就打算

一步一步写算法(之循环单向链表)

原文:一步一步写算法(之循环单向链表) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 前面的博客中,我们曾经有一篇专门讲到单向链表的内容.那么今天讨论的链表和上次讨论的链表有什么不同呢?重点就在这个"循环"上面.有了循环,意味着我们可以从任何一个链表节点开始工作,可以把root定在任何链表节点上面,可以从任意一个链表节点访问数据,这就是循环的优势. 那么在实现过程中,循环单向链表有什么不同? 1)打印链表数据 void pri

01-(2)数据结构- 一步一步写算法(之循环单向链表)

前面的博客中,我们曾经有一篇专门讲到单向链表的内容.那么今天讨论的链表和上次讨论的链表有什么不同呢?重点就在这个"循环"上面.有了循环,意味着我们可以从任何一个链表节点开始工作,可以把root定在任何链表节点上面,可以从任意一个链表节点访问数据,这就是循环的优势. 那么在实现过程中,循环单向链表有什么不同? 1)打印链表数据 [cpp] view plain copy void print_data(const LINK_NODE* pLinkNode) { LINK_NODE* pI

数据结构与算法系列四(单链表)

1.引子 1.1.为什么要学习数据结构与算法? 有人说,数据结构与算法,计算机网络,与操作系统都一样,脱离日常开发,除了面试这辈子可能都用不到呀! 有人说,我是做业务开发的,只要熟练API,熟练框架,熟练各种中间件,写的代码不也能“飞”起来吗? 于是问题来了:为什么还要学习数据结构与算法呢? #理由一: 面试的时候,千万不要被数据结构与算法拖了后腿 #理由二: 你真的愿意做一辈子CRUD Boy吗 #理由三: 不想写出开源框架,中间件的工程师,不是好厨子 1.2.如何系统化学习数据结构与算法?

7. C#数据结构与算法 -- 存储结构(单链表)

C#定义并实现单链表 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Linked {     //单链表结点类,采用泛型       public class Node<T> {         private T data; //数据域,当前结点的数据           private 

【数据结构】算法 LinkList (Insertion Sort List 链表插入排序)

将一个单链表进行处理后,所得结果为一有序链表 Solution: 将原始链表逐个查询,插入新链表,在插入的同时对链表进行排序.时间复杂度O(n*n) public ListNode insertionSortList(ListNode head) { ListNode dummy = new ListNode(0); while (head != null) { ListNode node = dummy; while (node.next != null && node.next.val

复习下C 链表操作(单向链表)

Object-C 作为C 的包装语言(运行时.消息机制).如果不熟悉C 的话实在玩得太肤浅. 随便深入oc 内部都会接触到C. runtime .GCD.Block.消息机制... 所有强大的功能无不用的 包装体(struct 结构体).使用GCC/Clang (可以google 下.Clang 比GCC 更优化,) 编译指令. 转换OC 为 C . 终端 使用Clang 命令参考 clang -rewrite-objc file.m 查看file.cpp 文件为编译转换的C 单向链表 创建 .

链表问题----将单向链表按某值划分成左边小、中间相等、右边大的形式

将单向链表按某值划分成左边小.中间相等.右边大的形式 给定一个单向链表的头节点head,节点的值类型是整数,再给定一个整数 pivot,实现一个调整链表的函数,使得左半部分的值都是小于pivot的节点,中间部分都是等于pivot的节点,右边部分都是大于pivot的节点,对于左半部分.中间.右半部分内部的顺序没有要求. 如果对于三部分内部的顺序也是有要求,即内部顺序各个节点的顺序与原来链表中的各个节点的先后顺序相同. [解析] 普通问题: 首先遍历一遍链表,得到链表的长度,将链表元素依次放到数组中

java 中的JDK封装的数据结构和算法解析(集合类)----链表 List 之 LinkedList

List 只要有两个实现类(ArrayList 和linkedList ),ArryList是基于数组实现,LinkedList是基于链表实现,下面是小弟对LinkedList的一点理解: LinkedList :基于链表实现的集合        双链接列表实现{ @code  List}和{ @code   Deque} 接口.实现了所有可选列表操作,和许可元素(including{ @code  null}). 首先对实现的接口分析一下: Deque  (双端队列): 这种队列允许在队列头和