数据结构-Java实现链表
2016-12-02 18:42
591 查看
概念
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间。本文讲述使用Java实现单向链表、以及如何使用数据来实现单向链表
单向链表的Java实现
链表节点结构package com.billJiang.stack; /** * Created by billJiang on 2016/11/30. * 单向链表节点 */ public class Node<T> { private T item; private Node<T> next; public Node() { this.item = null; this.next = null; } public Node(T item, Node<T> next) { this.item = item; this.next = next; } public T getItem() { return item; } public void setItem(T item) { this.item = item; } public Node<T> getNext() { return next; } public void setNext(Node<T> next) { this.next = next; } }
链表实现
package com.billJiang.link; import com.billJiang.stack.Node; /** * Created by billJiang on 2016/12/2. * 单项链表 */ public class Link<T> { private int size = 0; private Node<T> first; private Node<T> last; public void add(int index, T element) { //TODO 书本60 61页有问题 if (index <= size && index >= 0) { if (index == 0) { addFirst(element); } else if (index == size) { addLast(element); } else { Node node = this.get(index - 1); Node next = node.getNext(); Node cur = new Node(element, next); node.setNext(cur); size++; } } else { throw new IndexOutOfBoundsException("索引越界"); } } //获取链表中的数据 public Node get(int index) { Node node = first; int i = 0; while (node != null) { if (index == i) { return node; } i++; node = node.getNext(); } return null; } public T getValue(int index) { return this.get(index) == null ? null : (T) this.get(index).getItem(); } public void addFirst(T element) { if (size == 0) fillStart(element); else { Node<T> node = new Node(element, first); first = node; size++; } } public void addLast(T element) { Node<T> node = new Node(element, null); last.setNext(node); last = node; size++; } public boolean isEmpty() { return first == null && last == null; } public void fillStart(T element) { Node<T> node = new Node(element, null); first = node; last = first; size++; } public void remove(int index) { if (index < size && index >= 0) { if (index == 0) { removeFirst(); } else if (index == size - 1) { removeLast(); } else { Node temp = this.get(index); Node pre = this.get(index - 1); pre.setNext(temp.getNext()); temp = null; size--; } } else { throw new IndexOutOfBoundsException("索引越界"); } } public void removeFirst() { Node temp = first; first = temp.getNext(); temp = null; //如果只有一个元素,则first为null,将last也置为null if (first == null) { last = null; } size--; } public void removeLast() { //找到倒数第二个 Node node = this.get(size - 2); node.setNext(null); last = node; size--; } //链表反转 public void reverse(){ if(isEmpty()||size==1){ return; } Node pre=first; last=pre; for(Node node=first.getNext();node!=null;){ Node temp=node.getNext(); node.setNext(pre); pre=node; node=temp; } last.setNext(null); first=pre; } public void printAll(){ for(Node<T> node=first;node!=null;node=node.getNext()){ System.out.print("-->"+node.getItem().toString()); } } }
测试
package com.billJiang.link; /** * Created by billJiang on 2016/12/2. */ public class LinkTest { public static void main(String[] args) { Link<Integer> link=new Link<Integer>(); link.add(0,1); link.add(1,2); link.add(2,3); link.add(3,4); link.add(4,5); link.printAll(); link.remove(3); System.out.println(); System.out.println("------after romeve--------"); link.printAll(); link.reverse(); System.out.println(); System.out.println("----after reverse-------"); link.printAll(); System.out.println(); System.out.println("hello world"); } }
使用数组实现链表
节点结构定义package com.billJiang.link; /** * Created by billJiang on 2016/12/2. * 使用数组实现链表 */ public class Element<T> { T data; int nextIndex; public Element(T data,int nextIndex) { this.data=data; this.nextIndex=nextIndex; } }
具体实现
package com.billJiang.link; /** * Created by billJiang on 2016/12/2. * 使用数据模拟链表 */ public class LinkArray<T> { private Element[] items; private int size = 0;//元素个数 private int unused_head = 0; //存储内容链表的头尾位置 private int first; private int last; public LinkArray(int capacity) { items = new Element[capacity]; for (int i = 0; i < capacity - 1; i++) { items[i] = new Element<>(null, i + 1); } items[capacity - 1] = new Element<>(null, -1); } public void add(int index, T data) { if (index < 0 || index > size) { throw new IndexOutOfBoundsException("索引越界"); } if (checkFull()) { return;//满了 } if (index == 0) { addFirst(data); } else if (index == size) { addLast(data); } else { //获取要插入位置的前一个元素 Element e = this.get(index - 1); items[unused_head].data = data; int unused = items[unused_head].nextIndex; items[unused_head].nextIndex = e.nextIndex; e.nextIndex = unused_head; unused_head = unused; size++; } } public void addFirst(T data) { if (this.isEmpty()) { fillStart(data); size++; } else { //空链表的下一个索引下标 int index = items[unused_head].nextIndex; items[unused_head].data = data; items[unused_head].nextIndex = first; first = unused_head; unused_head = index; size++; } } public void addLast(T data) { int index = items[unused_head].nextIndex; items[unused_head].data = data; items[unused_head].nextIndex = -1; items[last].nextIndex = unused_head; last = unused_head; unused_head = index; size++; } public void remove(int index) { if (index < 0 || index > size - 1) { throw new IndexOutOfBoundsException("索引越界"); } if (index == 0) { removeFirst(); } else { if (isEmpty()) return; Element pre = get(index - 1); int del = pre.nextIndex; Element delElement = items[del]; pre.nextIndex = delElement.nextIndex; if (index == size - 1) { if (index >= 2) last = get(index - 2).nextIndex; else if (index == 1) { last = first; } } delElement.nextIndex = unused_head; unused_head = del; size--; } } public void removeFirst() { Element e = items[first]; if (size == 1) { last = first; } items[first].data = null; items[first].nextIndex = unused_head; unused_head=first; first = e.nextIndex; size--; } public Element get(int index) { Element e = items[first]; for (int i = 0; i < index; i++) { e = items[e.nextIndex]; } return e; } public boolean isEmpty() { return size == 0; } public void fillStart(T data) { Element element = items[unused_head]; element.data = data; first = unused_head; last = unused_head; unused_head = element.nextIndex; element.nextIndex = -1; } public boolean checkFull() { if (size == items.length) { return true; } return false; } }
测试
package com.billJiang.link; /** * Created by billJiang on 2016/12/2. */ public class LinkArrayTest { public static void main(String[] args) { LinkArray<Integer> la=new LinkArray<>(3); la.add(0,1); la.add(1,2); la.add(0,3); la.remove(0); la.add(1,4); } }
链表特点
1、物理空间不连续,空间开销大2、在运行时可以动态添加
3、查找元素需要顺序查找
4、操作略微复杂
相关文章推荐
- 使用java实现双向链表数据结构
- 【Java数据结构】2.4单循环链表的实现
- Java实现单链表数据结构
- 数据结构——单向传统链表(java实现)
- 数据结构Java实现04----循环链表、仿真链表
- 单链表-数据结构-java实现
- 数据结构java实现之双端链表
- 数据结构Java实现03----单向链表的插入和删除
- 数据结构链表(java版)的实现和思考
- 数据结构Java实现 ----循环链表、仿真链表
- java实现 数据结构:链表、 栈、 队列、优先级队列、哈希表
- 数据结构:二叉树的二叉链表存储--Java实现
- java与数据结构(4)---java实现双向循环链表
- 数据结构Java实现04----循环链表、仿真链表
- java数据结构之LinkedQueue(用链表实现的双端单向队列)
- 【Java数据结构】2.1单链表的实现
- java实现 数据结构:链表、 栈、 队列、优先级队列、哈希表
- 数据结构:线性表的链式存储(单向链表)--Java实现
- 数据结构Java实现04----循环链表、仿真链表
- 数据结构(三):链表的Java实现