数据结构与算法之单向链表 <一>

数据结构与算法是优秀的程序员都应该熟悉的
今天我们就来学习最简单也是最常用的算法之一 单向链表
首先我们应该明白链表优缺点是啥

链表的优点
能在常数时间内拓展 这比数组要好得多,创建数组时必须分配一定大小的内存,如果需要扩充数组,那么 必须创建一个大的新数组然后将原数组中的元素复制过去耗费大量时间

链表缺点链表有许多不足 主要缺点在于访问单个元素时间耗费过大,数组访问任意元素的时间开销是O(1) 而链表在最差的情况下是O(n)
还有链表的额外指针引用浪费内存

既然优缺点我们都明白了,任何东西都不可能是十全十美,现在我们开始实现链表算法

首先创建节点对象

//节点对象 对象应该包含储蓄的数据和指向下一个节点对象
//利用泛型 将储存的数据类型交给使用者来选择,大大提升灵活性
public class Node<E> {
    // 储存的数据
    private E data;
    // 下一个节点
    private Node<E> next;

    public E getData() {
        return data;
    }

    public void setData(E data) {
        this.data = data;
    }

    public Node<E> getNext() {
        return next;
    }

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

接下来创建链表对象并且实现一些功能


public class OneWayLinkedList<E> {

    private Node<E> headNode;
    private Node<E> endNode;

    // 在链表最后增加链表节点
    public void add(E obj) {
        Node<E> node = new Node<>();
        node.setData(obj);
        // 如果链表为空 则首尾节点都指向第一个节点
        if (headNode == null) {
            headNode = node;
            endNode = node;
        } else {
            // 不为空 将尾节点指向新增节点
            endNode.setNext(node);
            // 尾节点后移
            endNode = node;
        }
    }

    // 在指定中间位置增加节点
    public void add(int index, E element) {
        Node<E> node = new Node<>();
        node.setData(element);

        if (headNode == null) {
            throw new NullPointerException("空链表");
        }
        // 判断位置是否超出界限
        else if ((index < 0) || (index > this.size())) {
            throw new ArrayIndexOutOfBoundsException("超出范围");
        } else {
            // 首节点插入
            if (index == 0) {
                node.setNext(headNode);
                headNode = node;
            }
            // 尾节点插入
            else if (index == this.size()) {
                endNode.setNext(node);
                endNode = node;
            }
            // 中间插入
            else {
                Node<E> hnode = headNode;
                // 将首节点移动到插入节点的前一个节点
                for (int i = 1; i <= index - 1; i++) {
                    hnode = hnode.getNext();
                }
                node.setNext(hnode.getNext());
                hnode.setNext(node);
            }
        }
    }

    // 移除此列表中指定位置上的元素
    public void remove(int index) {

        if (headNode == null) {
            throw new NullPointerException("空链表");
        } else if ((index < 0) || (index >= this.size())) {
            throw new ArrayIndexOutOfBoundsException("超出范围");
        } else {
            // 保护头结点
            Node<E> hnode = headNode;
            // 删除首节点
            if (index == 0) {
                headNode = headNode.getNext();
                //System.out.println(index + "号:" + hnode.getData().toString() + "移除成功");
            }
            // 删除尾节点
            else if (index == (this.size() - 1)) {
                while (hnode.getNext() != null) {
                    hnode=hnode.getNext();
                }
                hnode.setNext(null);    
                //System.out.println(index + "号:" + endNode.getData() + " 移除成功");
                endNode = hnode;
            }
            // 删除中间节点
            else {
                for (int i = 1; i < index; i++) {
                    hnode = hnode.getNext();
                }
                //E data = hnode.getNext().getData();
                hnode.setNext(hnode.getNext().getNext());
                //System.out.println(index + "号:" + data.toString() + " 移除成功");
            }
        }
    }

    // 返回此列表中指定位置上的元素。
    public E get(int index) {
        if (headNode == null) {
            throw new NullPointerException("空链表");
        } else {
            // 遍历不到尾节点
            for (Node<E> node = headNode; node.getNext() != null; node = node.getNext()) {
                if (index == 0) {
                    return node.getData();
                }
                index--;
            }
            // 尾节点单独检测 为什么是0因为index多运行了一次
            if (index == 0) {
                return endNode.getData();
            } else
                throw new ArrayIndexOutOfBoundsException("超出范围");
        }

    }

    // 返回此列表的元素数。
    public int size() {
        if (headNode == null) {
            return 0;
        } else {
            Node<E> node = headNode;
            int count = 0;
            while (node.getNext() != null) {
                node = node.getNext();
                count++;
            }
            return count + 1;
        }
    }

    // 用指定的元素替代此列表中指定位置上的元素。
    public E set(int index, E element) {
        //删除指定位置的元素
        this.remove(index);
        //插入指定位置元素
        this.add(index, element);
        return element;
    }

//  @Test
//  public void test() {
//
//      OneWayLinkedList<Integer> oneWayLinkedList = new OneWayLinkedList<>();
//      for (int i = 0; i < 20; i++)
//          oneWayLinkedList.add(i);
//      System.out.println(oneWayLinkedList.get(19));
//      oneWayLinkedList.set(19, 15);
//      System.out.println(oneWayLinkedList.get(19));
//  }

    public Node<E> getHeadNode() {
        return headNode;
    }

    public void setHeadNode(Node<E> headNode) {
        this.headNode = headNode;
    }

    public Node<E> getEndNode() {
        return endNode;
    }

    public void setEndNode(Node<E> endNode) {
        this.endNode = endNode;
    }

}

至此单向链表基础功能已经实现了。希望对大家有所帮助。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值