1. 程式人生 > >談談靜態連結串列(JAVA實現)

談談靜態連結串列(JAVA實現)

我認為靜態連結串列對現在主流的語言沒有什麼用了。不過最近還是研究一下。

靜態連結串列其實就是一個數組

這個陣列的每一個單元包括了儲存資料的容器 data 和 指向下一個資料位置的容器 cur。如果是要參加工作的程式設計師,我認為沒有必要學習這種結構。我覺得這種方法就有點像是以前沒有指標的語言缺陷而產生這麼一個補救方法而已。現在的C java 都支援動態連結串列了。所以不是為了考試沒必要學這個。(個人觀點,不對勿噴)

下面是原始碼(JAVA)

import java.util.Scanner;

/*
 *	link 中儲存著兩個連結串列,一個是已經放入資料的連結串列(表頭由head記錄),一個是空閒未放入資料的連結串列(表頭由current記錄)
 */
public class StaticLink {

	element[] link = null;		//儲存資料的陣列
	int current = 0;			//記錄下一個可用空閒容器的下標
	int head = 0;				//記錄當前靜態連結串列頭的下標
	int length = 0;				//記錄當前裝有用資料的大小
	int MAXSIZE = 0;			//記錄靜態連結串列可裝的最大空間
	
	class element				//相當於連結串列中的空間單元
	{
		int data;				//記錄存入的資料
		int cur;				//記錄下一個數據的下標
	}
	
	public StaticLink(int size)		//初始化靜態列表
	{
		link = new element[size];
		
		for(int i = 0; i < size; i++)
		{
			link[i] = new element();
			link[i].data = -1;
			link[i].cur = i + 1;	//下標0的單元指向下標1的單元
		}
		current = 0;
		head = 0;
		length = 0;
		MAXSIZE = size;
		
		System.out.println("初始化靜態連結串列...");
	}
	
	public int add(int data)		//向當前靜態連結串列的後面新增一個數據
	{
		if(length < MAXSIZE)		//檢查是否還有空閒空間可以分配資料
		{
			link[current].data = data;		//將當前空閒單元存入資料
			current = link[current].cur;	//將current指向下一個空閒單元
			length++;						//實際使用空間增加1
			System.out.println("成功新增資料:" + data);
			return 0;
		}
		System.out.println("新增資料失敗");
		return -1;
	}
	
	public int delete()								//刪除當前靜態連結串列最後一個數據
	{
		if(length > 0 && link != null)				//判斷是否有資料可以刪除
		{
			int temp = current;						//暫時記錄當前空閒單元的下標
			current = getTrulyIndex(length - 1);	//將要刪除的使用單元加入到空閒單元鏈中
			link[current].cur = temp;				//將這個剛加入的單元連結上空閒空間
			length--;								//實際使用空間自減1
			System.out.println("成功刪除資料:" + link[current].data);
			return 0;
		}
		System.out.println("刪除資料失敗");
		return -1;
	}
	
	public int insert(int data, int index)			//從指定的下標的地方插入資料
	{
		if(length < MAXSIZE && link != null && index < length && index >= 0)	//判斷是否有空間可以插入新資料和判斷當前輸入的下標是否在範圍內
		{
			int tCurrent = current;					//儲存當前空閒單元的下標
			current = link[current].cur;			//將current指向下一個空閒單元
													//上面這兩個語句。相當於在空閒鏈中拿出一個單元出來儲存資料
			
			if(index == 0)							//當要插入的位置在最前面
			{
				link[tCurrent].data = data;			//將拿出的空閒單元存入資料
				link[tCurrent].cur = head;			//將這個單元指向原來的頭位置下標
				head = tCurrent;					//重新設定head指向的位置
			}
			else if(index == length - 1)			//當要插入的是在靜態連結串列末端
			{
				link[tCurrent].data = data;			//放入資料
			}
			else									//要插入的位置前後都有空間單元的時候
			{
				int preIndex = getTrulyIndex(index - 1);	//獲取要插入的前一個空間單元的index
				
				link[tCurrent].cur = link[preIndex].cur;	//將要插入位置的前一個單元原來的cur賦值給現在要插入的單元的cur(cur:儲存下一個單元的位置下標)
				link[tCurrent].data = data;					//放入資料		
				link[preIndex].cur = tCurrent;				//將要插入位置的前一個單元指向現在要插入單元的位置
			}
			length++;										//大小自增1
			System.out.println("成功在 " + index + " 插入資料: " + data);
			return 0;
		}
		System.out.println("在" + index + "插入資料失敗");
		return -1;
	}
	
	public int delete(int index)						//刪除給定位置的資料
	{
		if(length > 0 && link != null && index >= 0 && index <= length - 1)		//判斷是否有資料可以刪除
		{
			if(index == 0)								//判斷是否要刪除第一個單元
			{
				int tHead = head;						//儲存當前的head
				head = link[head].cur;					//將head指向一下單元
				link[tHead].cur = current;				//將刪除的單元加入空閒連結串列
				current = tHead;						//將current指向空閒鏈的第一個單元
			}
			else if(index == (length - 1))				//判斷是否要刪除最後一個單元
			{
				int last = getTrulyIndex(length - 1);	//獲取最後一個單元的位置
				if(last != -1)							//如果獲取位置成功
				{
					link[last].cur = current;			//將刪除的單元加入空閒鏈中
					current = last;						//將current指向空閒鏈的第一個單元
				}
			}
			else									//判斷是否要刪除第一個到最後一個(單元)之間的單元
			{
				int preIndex = getTrulyIndex(index - 1); //獲取要刪除單元的前一個單元的位置
				int temp = current;						 //儲存current的值
				current = link[preIndex].cur;			 //將要刪除的單元鏈入空閒鏈
				link[preIndex].cur = link[current].cur;	 //將上一個單元重新指向到下一個單元,例如A、B、C 刪除 B ,這個語句相當於 ##將 A 從指向 B 重新指向為 C ##(即改變A的指向)
				link[current].cur = temp;				 //將刪除單元鏈入空閒鏈
			}
			length--;									 //大小自減1
			System.out.println("成功在 " + index + " 刪除資料: " + link[current].data);
			return 0;
		}
		System.out.println("在" + index + "刪除資料失敗");
		return -1;
	}
	
	
	
	public int getTrulyIndex(int index)				//獲取給定下標的實際下標
	{
		int i = 0;
		int tHead = head;
		if(link != null)
		{
			while(i < index)						//這個是實現的重要程式碼
			{
				tHead = link[tHead].cur;			//每次執行這個語句的時候獲取下一個真正的位置下標
				i++;
			}
			if(i == index)							//判斷否是獲得真正的下標
			{
				return tHead;						//返回真正的下標
			}
		}

		return -1;
	}
	
	public int get(int index)						//獲取給定下標儲存資料
	{
		int tIndex = getTrulyIndex(index);
		if(tIndex != -1 && link != null)
		{
			return link[tIndex].data;
		}
		
		return -1;
	}
	
	
	public static void main(String[] args)			//這裡的測試程式碼,與靜態連結串列沒關係
	{
		int size = -1;
		int[] original = null;
		if(args != null && args.length == 1)
		{
			size = Integer.valueOf(args[0]);
		}
		else
		{
			Scanner sc = new Scanner(System.in);
			System.out.print("輸入測試大小<大於 10以上 >: ");
			size = sc.nextInt();
		}
		while(size == -1)
		{
			System.out.print("輸入錯誤,請重新輸入: ");
			Scanner sc = new Scanner(System.in);
			size = sc.nextInt();
		}
		
		original = new int[size - 5];
		
		StaticLink sl = new StaticLink(size);
		for(int i = 0; i < size - 5; i++)
		{
			sl.add(i);
			original[i] = i;
		}
		
		sl.delete();
		if(size > 3)
		{
			sl.insert(20, 2);
			sl.delete(1);
		}
		else
		{
			sl.insert(20, 0);
			sl.delete(0);
		}
		
		System.out.print("\n操作前的連結串列內容: ");
		for(int i = 0; i < original.length; i++)
		{
			System.out.printf("%d ",original[i]);
		}
		
		System.out.print("\n操作後的連結串列內容: ");
		for(int j = 0; j < sl.length; j++)
		{
			System.out.printf("%d ",sl.get(j));
		}
	}

}