天天看點

線性表線性表概述順序表單向循環連結清單雙向循環連結清單測試線性表

線性表概述

線性表是最基本、最簡單、也是最常用的一種資料結構。線上性表中資料元素之間的關系是線性,資料元素可以看成是排列在一條線上或一個環上。

線性表分為靜态線性表和動态線性表,常見的有順序表(靜态的)、單向連結清單(動态的)和雙向連結清單(動态的)。

線性表的操作主要包括:

(1)計算表的長度n。

(2)線性表是否為空

(3)将元素添加到線性表的末尾

(4)擷取第i個元素,0≤i < n。

(5)清除線性表

(6)傳回清單中首次出現指定元素的索引,如果清單不包含此元素,則傳回 -1。

(7)傳回清單中最後一次出現指定元素的索引,如果清單不包含此元素,則傳回 -1。

(8)将新元素插入第i個位置,0≤i < n,使原來的第i,i+1,…,n–1個元素變為第i+1,i+2,…,n個元素。

(9)更改第i個元素

(10)删除第i個元素,0≤i < n,使原來的第i+1,i+2,…,n–1個元素變為第i,i+1,…,n–2個元素

由此,對線性表抽象資料類型定義List接口如下:

List接口

package list;

public interface List {
	/**
	 * 将元素添加到線性表的末尾
	 */
	public void add(Object e);
	
	/**
	 * 清除線性表
	 */
	public void clear();
	/**
	 * 擷取i位置的元素
	 * @param i
	 * @return
	 */
	public Object get(int i);
	/**
	 * 傳回清單中首次出現指定元素的索引,如果清單不包含此元素,則傳回 -1。
	 * @param e
	 * @return
	 */
	public int indexOf(Object e);
	/**
	 * 在i後面插入一個元素e
	 * @param i
	 * @param e
	 */
	public void insert(int i, Object e);
	/**
	 * 判斷線性表是否為空
	 * @return
	 */
	public boolean isEmpty();
	/**
	 * 回清單中最後出現指定元素的索引,如果清單不包含此元素,則傳回 -1。
	 * @param e
	 * @return
	 */
	public int lastIndexOf(Object e);
	/**
	 *  移除清單中指定位置的元素
	 * @param i
	 */
	public void remove(int i);
	/**
	 * 用指定元素替換清單中指定位置的元素(可選操作)。
	 * @param i
	 * @param e
	 */
	public void set(int i, Object e);
	/**
	 * 傳回線性表的大小
	 * @return
	 */
	public int size();
}
           

順序表

結構模型

線性表線性表概述順序表單向循環連結清單雙向循環連結清單測試線性表

圖順序存儲結構記憶體結構示意圖 

源代碼

package list;

public class ArrayList implements List{
	/**
	 * 順序表預設的初始大小
	 */
	public static final int defLen = 10;
	private int maxLen;
	private Object[] array;
	private int size;
	
	public ArrayList() {
		size = 0;
		maxLen = defLen;
		array = new Object[defLen];
	}
	
	@Override
	public void clear() {
		size = 0;
	}

	@Override
	public Object get(int i) {
		if(i>=0 && i<size)
			return array[i];
		else
			return null;
	}

	@Override
	public int indexOf(Object e) {
		int i =0; 
		while(i<size && !array[i].equals(e)) {
			i++;
		}
		if(i < size)
			return i;
		else
			return -1;
	}

	@Override
	public void insert(int i, Object e) {
		if(i >= size) {
			i = size;
			if((size) >= maxLen)//如果插入數的位置大于順序表的最大容量,則擴大容量
				expand();
		}
		for(int j = size; j>i+1; j--) {
			array[j] = array[j-1];
		}
		array[i+1] = e;
		size ++;
	}

	@Override
	public boolean isEmpty() {
		if(size == 0)
			return true;
		else 
			return false;
	}

	@Override
	public int lastIndexOf(Object e) {
		int i = size-1;
		while(i>=0 && !array[i].equals(e)) {
			i--;
		}
		if(i>=0)
			return i;
		else
			return -1;
	}

	@Override
	public void remove(int i) {
		for(int j=i; j<size-1; j++) {
			array[j] = array[j+1];
		}
		size --;
	}

	@Override
	public void set(int i, Object e) {
		array[i] = e;
	}

	@Override
	public int size() {
		return size;
	}
	/**
	 * 當順序表的大小不夠時,擴充順序表的大小
	 */
	private void expand() {
		maxLen = 2*maxLen;
		Object newArray[] = new Object[maxLen];
		for(int i=0; i<size; i++) {
			newArray[i] = array[i];
		}
		array = newArray;
	}

	@Override
	public void add(Object e) {
		if(size >=maxLen)
			expand();
		array[size] = e;
		size ++;
	}
}
           

單向循環連結清單

結構模型

線性表線性表概述順序表單向循環連結清單雙向循環連結清單測試線性表

帶頭結點的單鍊結構

  (a)空鍊;  (b)非空鍊 

源代碼

package list;
/**
 * 連結清單的結點
 * @author luoweifu
 *
 */
class Node{
	Object data;	//資料元素
	Node next;		//後驅結點
	public Node() {
		this(null);
	}
	public Node(Object data) {
		this.data = data;
		this.next = null;
	}
}
/**
 * 帶頭結點的鍊式連結清單,下标從0開始; 
 * @author Administrator
 *
 */
public class LinkList implements List {
	Node head;	//頭結點
	int size;	//連結清單的大小
	public LinkList() {
		head = new Node();
		size = 0;
	}
	public LinkList(Object[] datas) {
		int n = datas.length;
		head = new Node();
		Node p = head;
		for(int i=0; i<n; i++) {
			p.next = new Node(datas[i]);
			p = p.next;
		}
		size = n;
	}
	@Override
	public void add(Object e) {
		Node p;
		if(0 == size) {
			p = head;
		} else {
			p = index(size-1);
		}
		p.next = new Node(e);
		size ++;
	}

	@Override
	public void clear() {
		head.next = null;
		size = 0;
	}

	@Override
	public Object get(int i) {
		Node p = index(i);
		return p.data;
	}
	
	private Node index(int i) {
		Node p = null;
		if(i>=0 && i<size){
			p = head;
			for(int j=0; j<=i; j++) {
				p = p.next;
			}
		} 
		return p;
	}

	@Override
	public int indexOf(Object e) {
		Node p = head.next;
		int i = 0;
		while(!p.data.equals(e)) {
			p = p.next;
			i++;
		}
		if(i<size)
			return i;
		else 
			return -1;
	}

	@Override
	public void insert(int i, Object e) {
		Node p = index(i);
		Node p2 = new Node(e);
		p2.next = p.next;
		p.next = p2;
		size ++;
	}

	@Override
	public boolean isEmpty() {
		if(size ==0)
			return true;
		else
			return false;
	}

	@Override
	public int lastIndexOf(Object e) {
		int i = size-1;
		while(!get(i).equals(e)) {
			i--;
		}
		if(i>=0)
			return i;
		else 
			return -1;
	}

	@Override
	public void remove(int i) {
		if(i>=0 && i<size) {
			Node p = null;
			if(i == 0)
				p = head;
			else {
				p = index(i-1);
			}
			p.next = index(i).next;
		}
		size --;
	}

	@Override
	public void set(int i, Object e) {
		Node p = index(i);
		p.data = e;
	}

	@Override
	public int size() {
		return size; 
	}
	
}
           

雙向循環連結清單

結構模型

線性表線性表概述順序表單向循環連結清單雙向循環連結清單測試線性表

帶頭結點的雙循環鍊結構

 (a)空鍊;  (b)非空鍊 

源代碼

package list;
/**
 * 連結清單的結點
 * @author luoweifu
 *
 */
class DlNode{
	Object data;
	DlNode prior, next;
	public DlNode() {
		this(null);
	}
	public DlNode(Object data) {
		this.data = data;	//資料元素
		this.prior = null;	//前驅結點
		this.next = null;	//後驅結點
	}
}
/**
 * 帶頭結點的雙向循環連結清單,下标從0開始; 
 * @author Administrator
 *
 */
public class DoubleLinkList implements List {
	DlNode head;	//頭結點
	int size;	//連結清單的大小
	public DoubleLinkList() {
		head = new DlNode();
		head.prior = head;
		head.next = head;
		size = 0;
	}
	public DoubleLinkList(Object[] datas) {
		int n = datas.length;
		head = new DlNode();
		DlNode p = head;
		DlNode p2 = null;
		for(int i=0; i<n; i++) {
			p2 = new DlNode(datas[i]);
			p.next = p2;
			p2.prior = p;
			p = p.next;
		}
		p2.next = head;
		head.prior = p2; 
		size = n;
	}
	@Override
	public void add(Object e) {
		DlNode p, p2;
		if(0 == size) {
			p = head;
		} else {
			p = index(size-1);
		}
		p2 = new DlNode(e);
		p.next = p2;
		p2.prior = p;
		p2.next = head;
		head.prior = p2;
		size ++;
	}

	@Override
	public void clear() {
		head.prior = head;
		head.next = head;
		size = 0;
	}

	@Override
	public Object get(int i) {
		DlNode p = index(i);
		return p.data;
	}
	
	private DlNode index(int i) {
		DlNode p = null;
		if(i>=0 && i<size){
			p = head;
			for(int j=0; j<=i; j++) {
				p = p.next;
			}
		} 
		return p;
	}

	@Override
	public int indexOf(Object e) {
		DlNode p = head.next;
		int i = 0;
		while(!p.data.equals(e)) {
			p = p.next;
			i++;
		}
		if(i<size)
			return i;
		else 
			return -1;
	}

	@Override
	public void insert(int i, Object e) {
		DlNode p = index(i);
		DlNode p2 = new DlNode(e);
		p2.next = p.next;
		p2.prior = p;
		p.next = p2;
		size ++;
	}

	@Override
	public boolean isEmpty() {
		if(size ==0)
			return true;
		else
			return false;
	}

	@Override
	public int lastIndexOf(Object e) {
		DlNode p = head.prior;
		int i = size-1;
		while(!p.data.equals(e)) {
			p = p.prior;
			i--;
		}
		if(i>=0)
			return i;
		else 
			return -1;
	}

	@Override
	public void remove(int i) {
		if(i>=0 && i<size) {
			DlNode p = null;
			if(i == 0)
				p = head;
			else {
				p = index(i-1);
			}
			DlNode p2 = index(i).next;
			p.next = p2.next;
			p2.next.prior = p;
		}
		size --;
	}

	@Override
	public void set(int i, Object e) {
		DlNode p = index(i);
		p.data = e;
	}

	@Override
	public int size() {
		return size; 
	}
	
}
           

測試線性表

package list;

public class Test {

	/**
	 * 測試線性表
	 * @param args
	 */
	public static void main(String args[]) {
		List list = new ArrayList();
		//List list = new LinkList();
		//List list = new DoubleLinkList();
		for(int i=0; i<10; i++) {
			list.add(new Integer(i));
		}
		list.remove(9);
		System.out.print("size;" + list.size() + "\n");
		System.out.println("isEmpty:" + list.isEmpty());
		System.out.print("第7個位置的元素:" + list.get(7) + "\n");	
		for(int i=0; i<list.size(); i++) {
			System.out.print(list.get(i) + "    ");
		}
		
		list.add(21);
		list.add(22);
		list.insert(3, new Integer(5));
		System.out.print("size:" + list.size() + "\n");
		System.out.print("第一次出現5的索引:" + list.indexOf(5) + "\n");
		System.out.print("最後一次出現5的索引:" + list.lastIndexOf(5) + "\n");
		list.set(0, new Integer(30));
		for(int i=0; i<list.size(); i++) {
			System.out.print(list.get(i) + "    ");
		}
	}
}
           

結果

size;9

isEmpty:false

第7個位置的元素:7

0    1    2    3    4    5    6    7    8    size:12

第一次出現5的索引:4

最後一次出現5的索引:6

30    1    2    3    5    4    5    6    7    8    21    22    

繼續閱讀