Java实现线性表

来源:互联网 发布:农村人口老龄化数据 编辑:程序博客网 时间:2024/06/04 19:13

线性表:用官方语言来讲就是具有相同属性的数据元素的一个有限序列;也就是说,元素之间是有顺序的,若元素存在多个,则第一个元素无前驱,最后一个元素无后继,其他每个元素都有且仅有一个前驱和后继;例如一年里的星座列表;

1.线性表有哪些操作呢?一般而言,线性表的操作有一下几种:

         初始化操作,即建立一个新的线性表;

         将线性表清空;

         获取线性表的长度;

         判断线性表是否为空;

         插入新元素(包括在指定位置),删除元素;

         返回线性表第n个位置的元素;

         遍历线性表;

上述操作是最基本的线性表操作,对于实际中更为复杂的操作,都可以用这些基本的组合来完成;


2.线性表的存储结构有顺序,链接,索引,散列等多种方式;顺序结构是其中最简单,最常见的一种;


顺序表;

           Java中,数据结构中的线性表,对应着Collection中的List接口,而线性表的顺序存储结构则对应于ArrayList;

代码如下:

package list;public class MyArrayList<T> implements Iterable<T>{private static final int DEFAULT_CAPACITY = 10;  //数组长度为10;private int theSize;      //线性表的长度;private T[] theItems;     //数组保存数据;public MyArrayList(){clear();}public void clear(){theSize = 0;ensureCapacity(DEFAULT_CAPACITY);}public int size(){return theSize;}public boolean isEmpty(){return size() == 0;}public T get(int index){if (index < 0 || index >= size())throw new ArrayIndexOutOfBoundsException();return theItems[index];}public T set(int idx, T newVal){if (idx < 0 || idx >= size())throw new ArrayIndexOutOfBoundsException();T old = theItems[idx];theItems[idx] = newVal;return old;}@SuppressWarnings("unchecked")public void ensureCapacity(int newCapacity)     //用于数组实例化,还有用于数组的扩充;{if (newCapacity < theSize)return;T[] old = theItems;theItems = (T[]) new Object[newCapacity];for (int i = 0; i < size(); i++){theItems[i] = old[i];}}public boolean add(T x){add(size(), x);return true;}public void add(int index, T x){if (theItems.length == size())ensureCapacity(size() * 2 + 1);  //添加前确认数组容量是否满了;for (int i = theSize; i > index; i--)theItems[i] = theItems[i - 1];theItems[index] = x;theSize++;}public T remove(int index){T removedItem = theItems[index];for (int i = index; i < size() - 1; i++)theItems[i] = theItems[i + 1];theSize--;return removedItem;}//通过内部类进行遍历线性表元素public java.util.Iterator<T> iterator(){return new ArrayListIterator();}private class ArrayListIterator implements java.util.Iterator<T>{private  int current = 0;public boolean hasNext(){return current < size();}public T next(){if (!hasNext())throw new java.util.NoSuchElementException();return theItems[current++];}public void remove(){MyArrayList.this.remove(--current);}}@SuppressWarnings("rawtypes")public static void main(String[] args){MyArrayList<Integer> list = new MyArrayList<Integer>();//添加数据;list.add(10);list.add(23);list.add(34);list.add(45);list.add(123);list.add(234);list.add(3,56);System.out.println(list.get(1));list.set(2,12);System.out.println(list.remove(1));MyArrayList.ArrayListIterator iterator = (MyArrayList.ArrayListIterator) list.iterator();while(iterator.hasNext()){System.out.print(iterator.next()+" ");}System.out.println();//也可以通过内部类的remove方法删除线性表的数据;iterator.remove();iterator = (MyArrayList.ArrayListIterator) list.iterator();while(iterator.hasNext()){System.out.print(iterator.next()+" ");}}}

来说下顺序结构的优点和缺点;

优点:可以快速的存取任一位置的元素,不必为表示表中元素之间的逻辑关系而增加额外的存储空间;

缺点:插入和删除操作需要移动大量元素,当线性表长度变化较大时,难以确定存储空间的容量,造成存储空间的“碎片”;


链式表:

       链表则对应于Java API中的LinkedList;

代码如下;

package list;public class LinkedList<T>{private Node<T> header = null; // 头结点int size = 0; // 表示链表长度public LinkedList(){this.header = new Node<T>();}public boolean add(T data){if (size == 0){header.data = data;} else{// 根据需要添加的内容,封装为结点Node<T> newNode = new Node<T>(data);// 得到当前最后一个结点Node<T> last = getNode(size - 1);// 在最后一个结点后加上新结点last.addNext(newNode);}size++;// 当前大小自增加1return true;}public boolean insert(int index, T data){Node<T> newNode = new Node<T>(data);// 得到第N个结点Node<T> cNode = getNode(index);newNode.next = cNode.next;cNode.next = newNode;size++;return true;}// 遍历当前链表,取得当前索引对应的元素private Node<T> getNode(int index){// 先判断索引正确性if (index > size || index < 0){throw new RuntimeException("索引值有错:" + index);}Node<T> tem = new Node<T>();tem = header;int count = 0;while (count != index){tem = tem.next;count++;}return tem;}// 根据索引,取得该索引下的数据public T get(int index){// 先判断索引正确性if (index >= size || index < 0){throw new RuntimeException("索引值有错:" + index);}Node<T> tem = new Node<T>();tem = header;int count = 0;while (count != index){tem = tem.next;count++;}T data = tem.data;return data;}public int size(){return size;}// 设置第N个结点的值public boolean set(int index, T e){// 先判断索引正确性if (index > size || index < 0){throw new RuntimeException("索引值有错:" + index);}// 得到第x个结点Node<T> cNode = getNode(index);cNode.data = e;return true;}public void display(){System.out.println("显示链表内容");Node<T> node = header;while (node != null){System.out.print(node.data + " ");node = node.next;}}// 用来存放数据的结点型内部类class Node<e>{private T data; // 结点中存放的数据Node(){}Node(T data){this.data = data;}Node<T> next; // 用来指向该结点的下一个结点// 在此结点后加一个结点void addNext(Node<T> node){next = node;}}public static void main(String[] args){LinkedList<String> list = new LinkedList<String>();for (int i = 0; i < 100; i++)list.add("add " + i);System.out.println(list.get(3));System.out.println(list.size());list.display();}}

而双向链表则可以表示为:

package list;public class MyLinkedList<T> implements Iterable<T>{private int theSize;           //链表长度private int modCount = 0;      //代表从构造方法以来,对链表所做改变的次数;private Node<T> beginMarker;   //头节点private Node<T> endMarker;     //尾节点public MyLinkedList(){clear();}//初始化,创建头节点和尾节点,然后设置大小为0public void clear(){beginMarker = new Node<T>(null, null, null);endMarker = new Node<T>(null, beginMarker, null);beginMarker.next = endMarker;theSize = 0;modCount++;}public int modeCount(){return modCount;}public int size(){return theSize;}public boolean isEmpty(){return size() == 0;}public boolean add(T x){add(size(), x);return true;}public void add(int index, T x){addBefore(getNode(index), x);}public T get(int index){return getNode(index).data;}public T set(int index, T newVal){Node<T> p = getNode(index);T oldVal = p.data;p.data = newVal;return oldVal;}public T remove(int index){return remove(getNode(index));}private T remove(Node<T> p){p.next.prev = p.prev;p.prev.next = p.next;theSize--;modCount++;return p.data;}private void addBefore(Node<T> p, T x){Node<T> newNode = new Node<T>(x, p.prev, p);p.prev.next = newNode;p.prev = newNode;theSize++;modCount++;}private Node<T> getNode(int index){Node<T> p;if (index < 0 || index > size())throw new IndexOutOfBoundsException();/* * 如果索引是该线链表前半部分的一个节点,那么我们将以向后的方式遍历该链表; * 否则,我们将从终端向前找; */if (index < size() / 2){p = beginMarker.next;for (int i = 0; i < index; i++)p = p.next;} else{p = endMarker;for (int i = size(); i > index; i--)p = p.prev;}return p;}public java.util.Iterator<T> iterator(){return new LinkedListIterator();}private class LinkedListIterator implements java.util.Iterator<T>{private Node<T> current = beginMarker.next;private int expectedModCount = modCount;private boolean okToRemove = false;public boolean hasNext(){return current != endMarker;}public T next(){if (modCount != expectedModCount)throw new java.util.ConcurrentModificationException();if (!hasNext())throw new java.util.NoSuchElementException();T nextItem = current.data;current = current.next;okToRemove = true;return nextItem;}public void remove(){if (modCount != expectedModCount)throw new java.util.ConcurrentModificationException();if (!okToRemove)throw new IllegalStateException();MyLinkedList.this.remove(current.prev);okToRemove = false;expectedModCount++;}}private static class Node<T>{public T data;             //数据public Node<T> prev;       //上一个节点public Node<T> next;       //下一个节点public Node(T d, Node<T> p, Node<T> n){data = d;prev = p;next = n;}}@SuppressWarnings("rawtypes")public static void main(String[] args){MyLinkedList<String> list = new MyLinkedList<String>();list.add("I");list.add("am");list.add("a");list.add("man");System.out.println(list.size());System.out.println(list.get(1));list.set(1,"is");System.out.println(list.remove(2));System.out.println(list.modeCount());MyLinkedList.LinkedListIterator iterator = (MyLinkedList.LinkedListIterator)list.iterator();while(iterator.hasNext()){System.out.print(iterator.next()+" ");}}}

对比链表和顺序表,我们可以得到一些简单的结论;

(1)若线性表需要频繁查找,很少进行插入和删除操作时,宜采用顺序存储结构;

(2)若线性表需要频繁的插入和删除时,宜采用链表结构;

(3)当线性表中的元素个数变化较大或者根本不知道有多大时,最好用链表结构,这样可以不需要考虑存储空间的大小问题;

(4)而如果事先知道线性表的大致长度,比如一年12个月,那么这种情况下可以考虑用顺序结构;

(5)当然还要考虑实际情况,来综合平衡采用哪种数据结构更能满足和达到需求和性能;


感觉这个线性表总结的还可以:线性表分析及Java实现

参考的书有:《大话数据结构》《数据结构与算法分析 Java语言》《Java数据结构和算法》

0 0
原创粉丝点击