Java单链表实现

Java单链表实现

  • 单链表各位置插入结点
  • 单链表各位置删除结点
  • 单链表正逆向遍历结点

单链表是实现栈、队列、哈希表等多种数据结构的基础,在此总结一下Java单链表中不同位置插入节点、不同位置删除结点、正逆向遍历结点的方法,以备以后复习时用。本人菜鸟一枚,如有错误请各位大佬批评指正。

单链表插入结点,根据插入位置不同可以分为:
在头结点处插入结点,时间复杂度o(1),addFirst(int val)
在尾结点处插入结点,时间复杂度o(n),addLast(int val)
在任意位置插入结点,时间复杂度o(n),add(int index,int val)
单链表删除结点,根据插入位置不同可以分为:
在头结点处删除结点,时间复杂度o(1),deleteFirst()
在尾结点处删除结点,时间复杂度o(n),deleteLast()
在任意位置删除结点,时间复杂度o(n),delete(int index,int val)
单链表的遍历:
正向遍历,display()
逆向遍历,displayFromTail()

采用单链表实现栈(先入后出)的功能,可以采用addFirst()和deleteLast()方法封装为push()和pop()方法;
采用单链表实现队列(先入先出)的功能,可以采用addFirst()和deleteFirst()方法封装为enqueue()和dequeue()方法;

代码如下:

package chapter.two.bean;

public class ListNode {
    /***
     * 结点内部类
     * @author Janet
     *
     */
    private class Node{
        int val;
        Node next;
        Node(int val) {
            this.val = val;
        }
    }

    //私有字段
    private Node first = null;
    private int N = 0; 

    /***
     * 判断链表是否为空
     * @return
     */
    public boolean isEmpty() {
        return N==0;
    }

    /**
     * 返回链表结点数
     * @return
     */
    public int size() {
        return N;
    }

    /***
     * 在头结点处添加元素,时间复杂度o(1)
     * @param val
     */
    public void addFirst(int val) {
        if( isEmpty() ) {
            first = new Node(val);
            first.next = null;
        } else {
            Node newFirst = new Node(val);
            newFirst.next = first;
            first = newFirst;
        }
        N++;
    }

    /***
     * 在链表结尾处添加元素,时间复杂度o(n)
     * @param val
     */
    public void addLast(int val) {
        if( isEmpty() ) {
            first = new Node(val);
            first.next = null;
        } else {
            Node p = first;
            while( p.next != null ) {
                p = p.next;
            }
            //p为尾结点
            p.next = new Node(val);
            p.next.next = null;
        }
        N++;
    }

    /***
     * 在任意位置添加元素,时间复杂度o(n)
     * @param index
     * @param val
     * @throws Exception 
     */
    public void add(int index,int val) throws Exception {
        if( index>=size() || index<0 ) {
            throw new Exception("链表不存在该位置");
        } else {
            if( index==0 ) {
                addFirst(val);
                return;
            }
            Node p = first;
            for (int i = 1; i < index; i++) {
                p = p.next;
            }
            //在p处添加新节点
            Node q = new Node(val);
            q.next = p.next;
            p.next = q;
            N++;
        }
    }

    /***
     * 删除头结点并返回,时间复杂度o(1)
     * @return
     */
    public Node deleteFirst() {
        Node result = first;
        first = first.next;
        N--;
        return result;
    }

    /***
     * 删除最后一个结点并返回,时间复杂度o(1)
     * @return
     */
    public Node deleteLast() {
        Node p = first;
        while( p.next.next != null ) {
            p = p.next;
        }
        //要删除p.next
        Node result = p.next;
        p.next = null;
        N--;
        return result;
    }

    /***
     * 删除任意位置的结点并返回,时间复杂度o(n)
     * @param index
     * @return
     * @throws Exception
     */
    public Node delete(int index) throws Exception {
        if( index<0 || index>=size() ) {
            throw new Exception("链表不存在该位置");
        } else {
            if( index==0 ) {
                N--;
                return deleteFirst();
            } else {
                Node p = first;
                for (int i = 1; i < index-1; i++) {
                    p = p.next;
                }
                //p.next(q)为要删除的结点
                Node q = p.next;
                p.next = q.next;
                q.next = null;
                N--;
                return q;
            }
        }
    }

    /***
     * 正向遍历链表
     */
    public void display() {
        for (Node temp = first; temp!=null; temp=temp.next)
            System.out.println(temp.val);
    }

    /***
     * 逆向遍历链表
     */
    public void displayFromTail() {
        displayFromTail(first);
    }

    private void displayFromTail(Node p) {
        if( p != null ) {
            if( p.next != null ) {
                displayFromTail(p.next);
            }
            System.out.println(p.val);
        }       
    }
}
ListNode链表类中定义了私有字段
Node first:头结点
N:链表中结点个数,通过方法size()获取

在任意位置的插入删除中,约定链表的位置(index)从0开始

关于逆向遍历链表
参考剑指offer面试题5:从尾到头打印链表
要逆向遍历链表,可以考虑正向遍历链表,并依次把结点元素存到栈中,由于栈是递归的一种形式,可以由此想到用递归来解决。如果结点p有next域,就递归调用displayFromTail(p.next)即可。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值