算法:java实现无头单向非循环链表

在这里插入图片描述

有头单链表和无头单链表

  • 无头单链表如下:

在这里插入图片描述

  • 有头单链表
    在这里插入图片描述
    总结:
  • 有头结点表示第一个结点不保存数据,与其他数据节点区别开来
  • 无头结点表示第一个节点保存数据,与其他节点除了位置不同,其余一模一样

两种链表在查询更改的方式是一样的,存在区别的是插入数据和删除数据

无头单链表

插入数据

  • 中间节点插入数据
    (1)找到要插入位置的前一个节点
    (2)创造新节点

在这里插入图片描述
(3)新节点指向被插入节点的指针域
在这里插入图片描述
(4)前一个节点指向新节点
在这里插入图片描述

  • 第一个节点之前添加数据
    (1)创造新节点
    在这里插入图片描述

(2)新节点指向第一个节点
在这里插入图片描述

(3)设置新节点为第一个节点

在这里插入图片描述

  • 最后一个节点之前添加数据
    已知:当前尾节点为tail
    (1) 创建新节点
    在这里插入图片描述
    (2)尾节点tail指向新节点
    在这里插入图片描述

(3)设置新节点为tail
在这里插入图片描述

删除数据

反转链表

无头单链表实现

// 无头单链表
public class Singlelist {
    //链表可以没有头结点,不能没有头指针
    private Node top;  // 这里的top相当于第一个节点
    private Node tail;  // 用于尾部插入元素: 相当于最后一个车厢
    private int length = 0;

    public Singlelist() {
        top = null; // 刚开始的时候一个节点都没有

    }

    /*
    *  empty()函数返回真(true)如果链表为空,否则返回假
    * */
    public boolean empty(){
        return top == null;  // 一个节点都没有
    }

    /*
    * 获取list中元素的个数 size
    * */
    public int size(){
        return length;
    }

    /*
    * 在链表的尾部插入元素、
    *
    *      * 当前程序中,top指向车尾, 每次遍历链表都是从车尾开始的。
    *        如果离top越近就先出。  top指向最新生成的节点,先进先出, 尾插法
    * */
    public void push_back(int ele){
        Node node = new Node();
        node.setData(ele);

        if (empty()){ // 如果一个节点都没有
            top = node; // 那么就让头指针指向第一个节点: 这个节点的指针域为null,数据域为data、
            tail = node; // 用于尾部插入元素
        }else{
            node.setNext(top); // 当前节点指向首节点
            top = node;   // 当前节点就变成了受节点
        }

        length++;
    }

    /*
     * 在链表的首部插入元素:
     *     头插法就是在单链表的节点插入操作中,
     *     新的节点总是在前面,结果有点类似栈的先进后出
     * */
    public void push_front(int ele){
        Node node = new Node();
        node.setData(ele);

        if (empty()){
            tail = node;
            top = node;
        }else{
            tail.setNext(node);
            tail = node; // 尾节点后移动
        }

        length++;
    }

    public void reverse1(){
        if (empty() || size() == 1) {
            return;
        }

        Node pre = top;  // top 一定不为空, 如果为空则已经返回了, 当前长度1
        Node cur = pre.getNext();  // 不可能为空,因为如果长度为1也直接返回了,链表的长度至少为2
        Node fur = cur.getNext(); // 可能为空


        tail = pre;

        pre.setNext(null);
        while (cur != null){
            cur.setNext(pre); // 指向前驱

            pre = cur; // pre是不要了的,所以先去
            cur = fur;
            if (fur != null){ // fur不是最后一个节点
                fur = fur.getNext();
            }

            // 如果fur == null, 那么cur == null, 就会跳出循环
        }


        top = pre;
    }
    /*
     * 在链表的指定位置上插入元素
     * */
    public void insert(int pos, int ele){
        if (pos == 0){
            push_back(ele);
            return;
        }

        if (pos == length){
            push_front(ele);
            return;
        }


        Node t = searchNode(pos - 1); // 找到当前位置的前一个节点
        Node n = new Node();
        n.setData(ele);
        n.setNext(t.getNext());  // 新节点指向原来位置的节点
        t.setNext(n); // 前一个节点指向新节点
        length++;
    }

    // 从头节点开始查找第n个元素
    public Node searchNode(int pos){
        if (pos < 0 || pos > size() - 1){
            System.out.println("超出索引范围");
            return null ;
        }


        // 找到第n个元素
        Node temp = top;
        int i = 0;
        while (i < pos){
            temp = temp.getNext();
            i++;
        }

        return temp;
    }


    /*
    * 删除首节点的位置
    * */
    public void pop_back(){
        if (empty()){
            System.out.println("当前链表为空");
            return;
        }
        top = top.getNext(); // 头指针向下移动
        length--;
    }

    /*
     * 删除尾节点
     * */
    public void pop_front(){
        if (empty()){
            System.out.println("当前链表为空");
            return;
        }

        if (size() == 1){
            clear();
            return;
        }
        // 找到倒数第二个节点的位置
        Node t = searchNode(size() - 2);
        t.setNext(null);
        length--;
    }

    /*
     * 删除指定节点的位置
     * */
    public void pop_pos(int pos){
        if (empty()){
            System.out.println("当前链表为空");
            return;
        }

        if (pos < 0 || pos > size() - 1){
            System.out.println("超出索引");
            return;
        }

       if (pos == 0){
           pop_back();
           return;
       }

       if (pos == size() - 1){
           pop_front();
           return;
       }


        // 指定节点的前一个节点
        Node t = searchNode(pos - 1);
        t.setNext(t.getNext().getNext());
        length--;
    }


   // 删除链表中的所有元素 clear
    public void clear(){
        top = null;
        length = 0;
    }

    public void showList(){
        Node temp = top;  // 建立一个临时指针,获取到头指针

        while (temp != null){ // 只要头节点还是指向节点
            System.out.print(temp.getData() + " -> ");
            temp = temp.getNext(); // 临时节点移动到下一个节点位置
        }
        System.out.println();
    }
}

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值