所谓线性表就是具有一维线性的存储结构,一般有两种存储方式:顺序存储和链式存储。数组就是一种顺序的存储结构,ArrayList就是一种顺序表的实现类。那么来讲一下链式存储的链表。LinkedList则是采用链表实现的容器。
链表又分为单链表和双链表。
单链表
An称为An+1的前驱节点,A0称为头节点。单链表只有一个指向后面节点的指针。
结构形式:
java代码
private class Node<E>{
E item;
Node<E> next;
Node(E item,Node<E> next){
this.item = item;
this.next = next;
}
}
这个只是一个链表的结构类,我们需要一个容器来实现这个单链表的具体操作。
package com.creat.mylist;
/**
* Created by WHZ on 2017/8/10 0010.
*/
public class MySingleList<E>{
private Node<E> first;
private int size;
private class Node<E>{
E item;
Node<E> next;
Node(E item,Node<E> next){
this.item = item;
this.next = next;
}
}
public int size() {
return size;
}
public boolean isEmpty() {
return (size == 0);
}
public boolean contains(Object o) {
if(o == null){
for(Node<E> x = first; x != null; x = x.next){
if(x.item == null){
return true;
}
}
}else {
for(Node<E> x = first; x != null; x = x.next){
if(o.equals(x.item)){
return true;
}
}
}
return false;
}
public boolean add(E e) {
Node<E> node = new Node<E>(e,null);
if(first == null){
first = node;
}else {
Node<E> x = null;
for(x = first; x.next != null; x = x.next)
;
x.next = node;
}
size++;
return true;
}
public boolean remove(Object o) {
if(first != null){
if( o == null){
Node<E> temp = null;
for(Node<E> x = first; x != null; x = x.next){
if(x.item == null){
return removeNode(x, temp);
}
temp = x;
}
}else {
Node<E> temp = null;
for(Node<E> x = first; x != null; x = x.next){
if(o.equals(x.item)){
return removeNode(x, temp);
}
temp = x;
}
}
}
return false;
}
private boolean removeNode(Node<E> x, Node<E> temp){
if(x == first){
first = x.next;
size--;
return true;
}else {
temp.next = x.next;
size--;
return true;
}
}
public void clear() {
first = null;
size = 0;
}
public E get(int index) {
if(first != null && size > index && index >= 0){
Node<E> x = first;
for(int i = 0; i < index; i++){
x = x.next;
}
return x.item;
}else {
throw new IndexOutOfBoundsException("越界");
}
}
public E set(int index, E element) {
if(first != null && size > index && index >= 0){
Node<E> x = first;
for(int i = 0; i < index; i++){
x = x.next;
}
x.item = element;
return x.item;
}else {
throw new IndexOutOfBoundsException("越界");
}
}
public void add(int index, E element) {
if(first != null && size > index ){
Node<E> x = first;
Node<E> temp = null;
for(int i = 0; i < index; i++){
temp = x;
x = x.next;
}
Node<E> newNode = new Node<E>(element,x);
temp.next = newNode;
size++;
}else if(first == null && index == 0){
first = new Node<E>(element,null);
size++;
}else {
throw new IndexOutOfBoundsException("越界");
}
}
public int indexOf(Object o) {
if(first != null){
if( o == null){
int index = 0;
for(Node<E> x = first; x != null; x = x.next){
if(x.item == null){
return index;
}
index++;
}
}else {
int index = 0;
for(Node<E> x = first; x != null; x = x.next){
if(o.equals(x.item)){
return index;
}
index++;
}
}
}
return -1;
}
}
测试结果
package com.creat;
import com.creat.mylist.MySingleList;
import java.io.*;
public class App {
public static void main(String[] args ) throws IOException {
MySingleList<Integer> list = new MySingleList<Integer>();
list.add(1);
list.add(2);
list.add(3);
System.out.println("是否包含3:"+list.contains(3));
System.out.println("3的索引值:"+list.indexOf(3));
System.out.println("索引1上的数:"+list.get(1));
list.add(1,4);
for(int i = 0; i < list.size(); i++){
System.out.print("第"+i+"个数:"+list.get(i)+" ;");
}
System.out.println();
list.set(1,6);
for(int i = 0; i < list.size(); i++){
System.out.print("第"+i+"个数:"+list.get(i)+" ;");
}
System.out.println();
System.out.println("是否为空:"+list.isEmpty());
System.out.println("链表大小:"+list.size());
list.clear();
System.out.println("是否为空:"+list.isEmpty());
System.out.println("链表大小:"+list.size());
for(int i = 0; i < list.size(); i++){
System.out.print("第"+i+"个数:"+list.get(i)+" ;");
}
}
}
是否包含3:true
3的索引值:2
索引1上的数:2
第0个数:1 ;第1个数:4 ;第2个数:2 ;第3个数:3 ;
第0个数:1 ;第1个数:6 ;第2个数:2 ;第3个数:3 ;
是否为空:false
链表大小:4
是否为空:true
链表大小:0
双链表
单链表只拥有头节点,当我们需要增加或者修改尾部的节点时,往往需要遍历整个链表,这样花费了很多时间,所以产生了双链表,拥有头节点和尾节点,每个节点拥有指向前驱节点的指针和后驱节点的指针。java中的LinkedList正是采用了双链表来实现。
链表结构:
private class Node<E>{
Node<E> prev;
E item;
Node<E> next;
Node(Node<E> prev, E item, Node<E> next){
this.item = item;
this.prev = prev;
this.next = next;
}
}
简单的容器类:
package com.creat.mylist;
/**
* Created by WHZ on 2017/8/10 0010.
*/
public class MyLinkedList<E> {
private Node<E> first;
private Node<E> last;
private int size;
private class Node<E>{
Node<E> prev;
E item;
Node<E> next;
Node(Node<E> prev, E item, Node<E> next){
this.item = item;
this.prev = prev;
this.next = next;
}
}
public int size() {
return size;
}
public boolean isEmpty() {
return (size == 0);
}
public boolean contains(Object o) {
if(first != null){
if(o == null){
for(Node<E> x = first; x != null; x = x.next){
if(x.item == null){
return true;
}
}
}else {
for(Node<E> x = first; x != null; x = x.next){
if(o.equals(x.item)){
return true;
}
}
}
}
return false;
}
public boolean add(E e) {
Node<E> newNode = new Node<E>(last, e, null);
if(last == null){
first = newNode;
}else {
last.next = newNode;
}
last = newNode;
size++;
return false;
}
public boolean remove(Object o) {
if(first != null){
if(o == null){
for(Node<E> x = first; x != null; x = x.next){
if(x.item == null){
if(x == first){
x.next.prev = null;
first = x.next;
}else if(x == last){
x.prev.next = null;
last = x.prev;
}else {
x.next.prev = x.prev;
x.prev.next = x.next;
}
size--;
return true;
}
}
}else {
for(Node<E> x = first; x != null; x = x.next){
if(o.equals(x.item)){
if(x == first){
x.next.prev = null;
first = x.next;
}else if(x == last){
x.prev.next = null;
last = x.prev;
}else {
x.next.prev = x.prev;
x.prev.next = x.next;
}
size--;
return true;
}
}
}
}
return false;
}
public void clear() {
first = null;
last = null;
size = 0;
}
public E get(int index) {
if(first != null && size > index && index >= 0){
if(size/2 > index){
Node<E> temp = first;
for(int i = 0; i < index; i++){
temp = temp.next;
}
return temp.item;
}else {
Node<E> temp = last;
for(int i = size-index; i > 1; i--){
temp = temp.prev;
}
return temp.item;
}
}else{
throw new IndexOutOfBoundsException("越界");
}
}
public E set(int index, E element) {
if(first != null && size > index && index >= 0){
if(size/2 > index){
Node<E> temp = first;
for(int i = 0; i < index; i++){
temp = temp.next;
}
temp.item = element;
return temp.item;
}else {
Node<E> temp = last;
for(int i = size-index; i > 1; i--){
temp = temp.prev;
}
temp.item = element;
return temp.item;
}
}else{
throw new IndexOutOfBoundsException("越界");
}
}
public void add(int index, E element) {
if(first != null && size > index && index >= 0){
if(size/2 > index){
Node<E> x = first;
for(int i = 0; i < index; i++){
x = x.next;
}
Node<E> newNode = new Node<E>(x.prev, element, x);
if(x == first){
x.prev = newNode;
first = newNode;
}else {
x.prev.next = newNode;
x.prev = newNode;
}
}else {
Node<E> x = last;
for(int i = size-index; i > 1; i--){
x = x.prev;
}
Node<E> newNode = new Node<E>(x.prev, element, x);
if(x == first){
x.prev = newNode;
first = newNode;
}else {
x.prev.next = newNode;
x.prev = newNode;
}
}
size++;
}else{
throw new IndexOutOfBoundsException("越界");
}
}
public int indexOf(Object o) {
int index = 0;
for(Node<E> x = first; x != null; x = x.next){
if(o == null){
if(x.item == null){
return index;
}
}else {
if(o.equals(x.item)){
return index;
}
}
index++;
}
return -1;
}
}
测试结果:
package com.creat.mylist;
/**
* Created by WHZ on 2017/8/10 0010.
*/
public class MyLinkedClient {
public static void main(String[] args){
MyLinkedList<String> linkedList = new MyLinkedList<String>();
linkedList.add("whz");
linkedList.add("zdd");
linkedList.add("haiyoushui");
for(int i = 0; i < linkedList.size(); i++){
System.out.println("第"+i+"个是:"+linkedList.get(i));
}
System.out.println(linkedList.size());
linkedList.add(1,"没谁了");
for(int i = 0; i < linkedList.size(); i++){
System.out.println("第"+i+"个是:"+linkedList.get(i));
}
System.out.println("没谁了存在不:"+linkedList.contains("没谁了"));
System.out.println("没谁存在不:"+linkedList.contains("没谁"));
System.out.println("zdd在第几个:"+linkedList.indexOf("zdd"));
linkedList.remove("whz");
linkedList.remove("haiyoushui");
for(int i = 0; i < linkedList.size(); i++){
System.out.println("第"+i+"个是:"+linkedList.get(i));
}
linkedList.set(0,"whz");
for(int i = 0; i < linkedList.size(); i++){
System.out.println("第"+i+"个是:"+linkedList.get(i));
}
linkedList.clear();
System.out.println("是否为空:"+linkedList.isEmpty());
for(int i = 0; i < linkedList.size(); i++){
System.out.println("第"+i+"个是:"+linkedList.get(i));
}
}
}
第0个是:whz
第1个是:zdd
第2个是:haiyoushui
3
第0个是:whz
第1个是:没谁了
第2个是:zdd
第3个是:haiyoushui
没谁了存在不:true
没谁存在不:false
zdd在第几个:2
第0个是:没谁了
第1个是:zdd
第0个是:whz
第1个是:zdd
是否为空:true
总结:基于数组实现的集合在查找方面速度较快,数组是固定大小,所以在插入,删除方面速度较慢,插入时需要以后该位置之后的所有元素。基于链表实现的集合在插入,删除方面有很大的优势,在查找方面略疏于数组。