C++中有析構函數,用於銷燬對象時釋放內存,而Java中由於有gc(垃圾回收機制)因此就沒有析構函數,可是java有finalize() 方法,二者的用途相近。java
具體請參考連接:http://blog.csdn.net/jemasw/article/details/8470480node
什麼是線性表?數組
官方定義:線性表是n個數據元素的有限序列函數
順序表和鏈表互爲補充;spa
定義解讀:n個(個數),元素(能夠是複雜元素對象,也能夠是單個數據),有限(有限的),序列(是一個序列集合).net
線性表分爲兩大類:數組和鏈表指針
順序表對象
前驅:指定元素前一個元素blog
後繼:指定元素的後一個元素內存
優勢:能夠經過下標遍歷尋址,因此遍歷和尋址極爲快速。
缺點:插入和刪除元素,由於要移動後面的全部元素,因此較爲緩慢。
鏈表
單鏈表:
單鏈表,每一個節點分爲兩部分,分別爲 數據域 和 指針域
initChainList(); 初始化鏈表
void destroyList(); 銷燬鏈表,廢棄
boolean isListEmpty(); 判斷鏈表是否爲空
int listLength(); 獲取鏈表的長度
void clearList(); 清空鏈表的全部元素
Node listInsertHead(Node node); 插入頭節點
Node listInsertTail(Node node); 插入尾節點
Node insertElement(int i, Node node); 指定位置插入節點
Node deleteElement(int i); 刪除指定節點
Node getElement(int i); 獲取指定位置節點
int elementLocate(Node node); 獲取指定節點所在的位置
Node priorElement(Node node); 找到指定節點的前驅
Node nextElement(Node node); 找到指定節點的後繼
void listTraverse(); 遍歷鏈表
循環鏈表
簡單的說,就是首尾相連的單鏈表即尾節點的指針域指向首節點的位置
雙向鏈表
雙向鏈表,每一個節點分爲三部分,分別爲:
前指針域:順向指向下一個節點的位置
數據域:數據節點
後指針域:逆向指向下一個節點的位置
靜態鏈表
此處附上順序表的建立代碼:
package util; public class MyList { //線性表自己 private Object myList[]; //線性表的大小,即最大容量 private int listSize; //線性表的長度,即線性表中的元素個數 private int myLength; public MyList() { super(); } /** * 初始化線性表 - 順序表 * @param size */ public MyList(int size) { listSize = size; //申請線性表內存 myList = new Object[listSize]; myLength = 0; } /** * 銷燬線性表 */ public void DestroyList(){ myList = null; } /** * 清空線性表元素 */ public void clearList(){ myLength = 0; } /** * 判斷線性表是否爲空 * @return */ public boolean isListEmpty(){ return myLength == 0 ? true : false; } /** * 獲取線性表的元素個數 * @return */ public int listLength(){ return myLength; } /** * 獲取下標位置的元素 */ public Object getElement(int i) { //須要將i入參進行必定的限制,由於元素存在的位置座標僅限於0到線性表的個數減一(即0~myLength-1),因此若是i小於0或者i大於等於線性表的長度都斷定爲獲取失敗返回null if(i < 0 || i >= myLength){ return null; } return myList[i]; } /** * 獲取線性表中元素所在的位置(只獲取第一個遇到的位置) * @param element * @return */ public int elementLocate(Object element){ for (int i = 0; i <= myLength; i++){ if (element.equals(myList[i])) { return i; } } return -1; } /** * 獲取指定元素前驅 * @param element * @return */ public Object priorElement(Object element){ int i = elementLocate(element); if(i == -1){ //若是i==-1那麼則表示當前線性表中沒有找到元素,因此直接斷定失敗,返回null return null; }else if(i == 0){ //若是i==0則該元素自己就是第一個元素,前面不可能再有前驅,因此返回null return null; }else{ return myList[i - 1]; } } /** * 獲取指定元素後綴 * @param element * @return */ public Object nextElement(Object element){ int i = elementLocate(element); if(i == -1){ return null; }else if(i == myLength-1){ return null; }else{ return myList[i + 1]; } } /** * 在指定位置插入元素 * @param i * @param element * @return */ public Object insertElement(int i, Object element) { if(i < 0 || i > myLength) { return null; } //此處注意要從後向前依次將i後面的元素向後移位 for (int j = myLength-1; j >= i; j--){ //依次把前面的元素向後移位 myList[j + 1] = myList[j]; } myList[i] = element; myLength++; return element; } /** * 刪除指定位置元素 * @param i * @return */ public Object deleteElement(int i){ if (i < 0 || i >= myLength){ return null; } Object element = myList[i]; //此處注意要從前向後依次將i後面的元素向後移位,不用單獨執行刪除操做,由於在移位的過程當中已經把i座標的元素給覆蓋了 for (int j = i + 1; j < myLength; j++){ //依次把後面的元素向前移位 myList[j - 1] = myList[j]; } myLength--; return element; } /** * 遍歷線性表中的元素 */ public void listTraverse(){ for (int i = 0; i <= myLength-1; i++){ System.out.println(myList[i].toString()); } } }
此處附上鍊表的結構代碼:
package util; import test.entity.Node; public class MyChainList { private Node myChainList; private int listLength; /** * 初始化鏈表 */ public MyChainList() { //申請節點內存 myChainList = new Node(); myChainList.data = null; myChainList.next = null; listLength = 0; } /** * 銷燬鏈表,廢棄 */ public void destroyList(){ clearList(); myChainList = null; } /** * 判斷鏈表是否爲空 * @return */ public boolean isListEmpty(){ return 0 == listLength ? true :false; } /** * 獲取鏈表的長度 * @return */ public int listLength(){ return listLength; } /** * 清空鏈表的全部元素 */ public void clearList(){ Node currentNode = myChainList; //初始節點的下一個節點,爲第一個節點,找到第一個節點判斷是否爲空 while(null != currentNode.next){ Node temp = currentNode.next; //將當前節點刪除 currentNode = null; //查找下一個節點 currentNode = temp; } currentNode.data = null; currentNode.next = null; listLength = 0; } /** * 插入頭節點 * @param node * @return */ public Node listInsertHead(Node node){ //將第一個元素指向的下一個節點,存放備用 Node temp = myChainList.next; //從堆內存中申請空間,將數據放入內存 Node newNode = new Node(); if(null == newNode){ return null; } newNode.data = node.data; //讓新的節點指向,第一個節點原指向的節點 newNode.next = temp; //將node節點放入第一個節點的後面 myChainList.next = newNode; listLength ++; return newNode; } /** * 插入尾節點 * @param node * @return */ public Node listInsertTail(Node node){ Node currentNode = myChainList; //重第一個節點開始循環查找下一個節點,知道找到尾節點 while(null != currentNode.next) { currentNode = currentNode.next; } //從堆內存中申請空間,將數據放入內存 Node newNode = new Node(); if(null == newNode){ return null; } newNode.data = node.data; newNode.next = null; //將新節點插入尾節點的後面 currentNode.next = newNode; listLength ++; return newNode; } /** * 指定位置插入節點 * @param i * @param node * @return */ public Node insertElement(int i, Node node){ //判斷i是否合法 if (i < 0 || i > listLength){ return null; } //遍歷節點找到 i 位置的上一個節點 Node currentNode = myChainList; for (int j = 0; j < i; j++){ currentNode = currentNode.next; } Node newNode = new Node(); if (null == newNode){ return null; } newNode.data = node.data; //將原位於i位置的節點放入新節點的後面 newNode.next = currentNode.next; //將新節點,放入i上一個節點的後面 currentNode.next = newNode; listLength ++; return newNode; } /** * 刪除指定節點 * @param i * @return */ public Node deleteElement(int i){ if (i < 0 || i >= listLength){ return null; } //找到第i個節點,和i的上一個節點 Node currentNode = myChainList; Node currentNodeBefore = null; for (int j = 0; j <= i; j++){ currentNodeBefore = currentNode; currentNode = currentNode.next; } //將i位置後面的節點,放在i前面節點的後面 currentNodeBefore.next = currentNode.next; Node temp = currentNode; currentNode = null; listLength --; return temp; } /** * 獲取指定位置節點 * @param i * @return */ public Node getElement(int i){ //過濾i的合理範圍 if (i < 0 || i >= listLength){ return null; } // 找到第i個節點 Node currentNode = myChainList; for (int j = 0; j <= i; j++){ currentNode = currentNode.next; } return currentNode; } /** * 獲取指定節點所在的位置 * @param node * @return */ public int elementLocate(Node node){ //循環查找全部節點 Node currentNode = myChainList; int count = 0; while(null != currentNode.next){ currentNode = currentNode.next; //找到鏈表中第一個與指定節點匹配的節點 if (currentNode.data.equals(node.data)){ //返回當前循環的次數 return count; } //每執行一次表示當前位置沒有匹配的節點,注意不能放在if前面 count++; } return -1; } /** * 找到指定節點的前驅 * @param node * @return */ public Node priorElement(Node node){ //找到 指定節點 和 指定節點的 上一個節點 Node currentNode = myChainList; Node currentNodeBefore = null; while(null != currentNode.next){ currentNodeBefore = currentNode; currentNode = currentNode.next; //匹配到了第一個與指定節點相同的節點 if (node.data.equals(currentNode.data)){ //若是找到的對象是線性表中的第一個元素,那麼他就沒有前驅,返回null if (currentNodeBefore.equals(myChainList)){ return null; } return currentNodeBefore; } } return null; } /** * 找到指定節點的後繼 * @param node * @return */ public Node nextElement(Node node){ //遍歷線性表,找到指定節點 Node currentNode = myChainList; while(null != currentNode.next){ currentNode = currentNode.next; //若是找到了元素 if (currentNode.data.equals(node.data)){ //判斷該元素是否爲線性表中的最後一個元素,最後一個元素沒有後綴,直接返回null if (currentNode.next == null){ return null; } return currentNode.next; } } return null; } /** * 遍歷鏈表 */ public void listTraverse(){ //遍歷鏈表中的全部元素,依次打印出他們的 數據域 Node currentNode = myChainList; while(null != currentNode.next){ currentNode = currentNode.next; currentNode.printNode(); } } }