数据结构与算法之单向链表 <一>
2017-03-01 17:12
447 查看
数据结构与算法是优秀的程序员都应该熟悉的
今天我们就来学习最简单也是最常用的算法之一 单向链表
首先我们应该明白链表优缺点是啥
链表的优点
能在常数时间内拓展 这比数组要好得多,创建数组时必须分配一定大小的内存,如果需要扩充数组,那么 必须创建一个大的新数组然后将原数组中的元素复制过去耗费大量时间
链表缺点链表有许多不足 主要缺点在于访问单个元素时间耗费过大,数组访问任意元素的时间开销是O(1) 而链表在最差的情况下是O(n)
还有链表的额外指针引用浪费内存
既然优缺点我们都明白了,任何东西都不可能是十全十美,现在我们开始实现链表算法
首先创建节点对象
接下来创建链表对象并且实现一些功能
至此单向链表基础功能已经实现了。希望对大家有所帮助。
今天我们就来学习最简单也是最常用的算法之一 单向链表
首先我们应该明白链表优缺点是啥
链表的优点
能在常数时间内拓展 这比数组要好得多,创建数组时必须分配一定大小的内存,如果需要扩充数组,那么 必须创建一个大的新数组然后将原数组中的元素复制过去耗费大量时间
链表缺点链表有许多不足 主要缺点在于访问单个元素时间耗费过大,数组访问任意元素的时间开销是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; } }
至此单向链表基础功能已经实现了。希望对大家有所帮助。
相关文章推荐
- 数据结构与算法之双向链表 <二>
- 数据结构与算法之循环链表 <三>
- 数据结构之查找<一>
- 数据结构与算法 2、单向/双向链表
- 数据结构与算法(4)----->链表、二分搜索
- 数据结构与算法之散列(线性/平方/双平方探测法)<八>
- <二>java数据结构与算法 冒泡排序
- 数据结构——算法之(004)(输入一个单向链表,输出该链表中倒数第k个结点)
- 数据结构与算法之图的邻接表与邻接矩阵<十二>
- [数据结构算法学习] 单向链表
- <六>java数据结构与算法 栈
- 数据结构学习笔记<三>数据结构算法2.2具体实现
- C语言 数据结构与算法 单向链表
- 数据结构与算法之优先队列<九>
- 数据结构实例<三>(匹配链表所有元素删除后并返回新的链表)入门
- <三>java数据结构与算法 选择排序
- php学习第一章:PHP基础语法(三)数据结构与算法:2、单向链表
- 【数据结构与算法】链表1:单向链表(Java实现)
- 数据结构与算法之基础排序(冒泡/插入/选择)<十>
- 【数据结构&算法】数据结构之单向链表(练习)