概要
線性表是一種線性結構,它是具有相同類型的n(n≥0)個數據元素組成的有限序列。本章先介紹線性表的幾個基本組成部分:數組、單向鏈表、雙向鏈表;隨后給出雙向鏈表的C、C++和Java三種語言的實現。內容包括:
數組
單向鏈表
雙向鏈表
1. C實現雙鏈表
2. C++實現雙鏈表
3. Java實現雙鏈表
轉載請注明出處:http://www.cnblogs.com/skywang12345/p/3561803.html
更多內容
數組
數組有上界和下界,數組的元素在上下界內是連續的。
數組的特點是:數據是連續的;隨機訪問速度快。
數組中稍微復雜一點的是多維數組和動態數組。對於C語言而言,多維數組本質上也是通過一維數組實現的。至於動態數組,是指數組的容量能動態增長的數組;對於C語言而言,若要提供動態數組,需要手動實現;而對於C++而言,STL提供了Vector;對於Java而言,Collection集合中提供了ArrayList和Vector。
單向鏈表
單向鏈表(單鏈表)是鏈表的一種,它由節點組成,每個節點都包含下一個節點的指針。
表頭為空,表頭的后繼節點是"節點10"(數據為10的節點),"節點10"的后繼節點是"節點20"(數據為10的節點),...
單鏈表刪除節點
刪除"節點30"
刪除之前:"節點20" 的后繼節點為"節點30",而"節點30" 的后繼節點為"節點40"。
刪除之后:"節點20" 的后繼節點為"節點40"。
單鏈表添加節點
在"節點10"與"節點20"之間添加"節點15"
添加之前:"節點10" 的后繼節點為"節點20"。
添加之后:"節點10" 的后繼節點為"節點15",而"節點15" 的后繼節點為"節點20"。
單鏈表的特點是:節點的鏈接方向是單向的;相對於數組來說,單鏈表的的隨機訪問速度較慢,但是單鏈表刪除/添加數據的效率很高。
雙向鏈表
雙向鏈表(雙鏈表)是鏈表的一種。和單鏈表一樣,雙鏈表也是由節點組成,它的每個數據結點中都有兩個指針,分別指向直接后繼和直接前驅。所以,從雙向鏈表中的任意一個結點開始,都可以很方便地訪問它的前驅結點和后繼結點。一般我們都構造雙向循環鏈表。
表頭為空,表頭的后繼節點為"節點10"(數據為10的節點);"節點10"的后繼節點是"節點20"(數據為10的節點),"節點20"的前繼節點是"節點10";"節點20"的后繼節點是"節點30","節點30"的前繼節點是"節點20";...;末尾節點的后繼節點是表頭。
雙鏈表刪除節點
刪除"節點30"
刪除之前:"節點20"的后繼節點為"節點30","節點30" 的前繼節點為"節點20"。"節點30"的后繼節點為"節點40","節點40" 的前繼節點為"節點30"。
刪除之后:"節點20"的后繼節點為"節點40","節點40" 的前繼節點為"節點20"。
雙鏈表添加節點
在"節點10"與"節點20"之間添加"節點15"
添加之前:"節點10"的后繼節點為"節點20","節點20" 的前繼節點為"節點10"。
添加之后:"節點10"的后繼節點為"節點15","節點15" 的前繼節點為"節點10"。"節點15"的后繼節點為"節點20","節點20" 的前繼節點為"節點15"。
下面介紹雙鏈表的實現,分別介紹C/C++/Java三種實現。
實現代碼
雙向鏈表頭文件(double_link.h)
1 #ifndef _DOUBLE_LINK_H 2 #define _DOUBLE_LINK_H 3 4 // 新建“雙向鏈表”。成功,返回表頭;否則,返回NULL 5 extern int create_dlink(); 6 // 撤銷“雙向鏈表”。成功,返回0;否則,返回-1 7 extern int destroy_dlink(); 8 9 // “雙向鏈表是否為空”。為空的話返回1;否則,返回0。 10 extern int dlink_is_empty(); 11 // 返回“雙向鏈表的大小” 12 extern int dlink_size(); 13 14 // 獲取“雙向鏈表中第index位置的元素”。成功,返回節點指針;否則,返回NULL。 15 extern void* dlink_get(int index); 16 // 獲取“雙向鏈表中第1個元素”。成功,返回節點指針;否則,返回NULL。 17 extern void* dlink_get_first(); 18 // 獲取“雙向鏈表中最后1個元素”。成功,返回節點指針;否則,返回NULL。 19 extern void* dlink_get_last(); 20 21 // 將“value”插入到index位置。成功,返回0;否則,返回-1。 22 extern int dlink_insert(int index, void *pval); 23 // 將“value”插入到表頭位置。成功,返回0;否則,返回-1。 24 extern int dlink_insert_first(void *pval); 25 // 將“value”插入到末尾位置。成功,返回0;否則,返回-1。 26 extern int dlink_append_last(void *pval); 27 28 // 刪除“雙向鏈表中index位置的節點”。成功,返回0;否則,返回-1 29 extern int dlink_delete(int index); 30 // 刪除第一個節點。成功,返回0;否則,返回-1 31 extern int dlink_delete_first(); 32 // 刪除組后一個節點。成功,返回0;否則,返回-1 33 extern int dlink_delete_last(); 34 35 #endif
雙向鏈表實現文件(double_link.c)
1 #include <stdio.h> 2 #include <malloc.h> 3 4 /** 5 * C 語言實現的雙向鏈表,能存儲任意數據。 6 * 7 * @author skywang 8 * @date 2013/11/07 9 */ 10 // 雙向鏈表節點 11 typedef struct tag_node 12 { 13 struct tag_node *prev; 14 struct tag_node *next; 15 void* p; 16 }node; 17 18 // 表頭。注意,表頭不存放元素值!!! 19 static node *phead=NULL; 20 // 節點個數。 21 static int count=0; 22 23 // 新建“節點”。成功,返回節點指針;否則,返回NULL。 24 static node* create_node(void *pval) 25 { 26 node *pnode=NULL; 27 pnode = (node *)malloc(sizeof(node)); 28 if (!pnode) 29 { 30 printf("create node error!\n"); 31 return NULL; 32 } 33 // 默認的,pnode的前一節點和后一節點都指向它自身 34 pnode->prev = pnode->next = pnode; 35 // 節點的值為pval 36 pnode->p = pval; 37 38 return pnode; 39 } 40 41 // 新建“雙向鏈表”。成功,返回0;否則,返回-1。 42 int create_dlink() 43 { 44 // 創建表頭 45 phead = create_node(NULL); 46 if (!phead) 47 return -1; 48 49 // 設置“節點個數”為0 50 count = 0; 51 52 return 0; 53 } 54 55 // “雙向鏈表是否為空” 56 int dlink_is_empty() 57 { 58 return count == 0; 59 } 60 61 // 返回“雙向鏈表的大小” 62 int dlink_size() { 63 return count; 64 } 65 66 // 獲取“雙向鏈表中第index位置的節點” 67 static node* get_node(int index) 68 { 69 if (index<0 || index>=count) 70 { 71 printf("%s failed! index out of bound!\n", __func__); 72 return NULL; 73 } 74 75 // 正向查找 76 if (index <= (count/2)) 77 { 78 int i=0; 79 node *pnode=phead->next; 80 while ((i++) < index) 81 pnode = pnode->next; 82 83 return pnode; 84 } 85 86 // 反向查找 87 int j=0; 88 int rindex = count - index - 1; 89 node *rnode=phead->prev; 90 while ((j++) < rindex) 91 rnode = rnode->prev; 92 93 return rnode; 94 } 95 96 // 獲取“第一個節點” 97 static node* get_first_node() 98 { 99 return get_node(0); 100 } 101 102 // 獲取“最后一個節點” 103 static node* get_last_node() 104 { 105 return get_node(count-1); 106 } 107 108 // 獲取“雙向鏈表中第index位置的元素”。成功,返回節點值;否則,返回-1。 109 void* dlink_get(int index) 110 { 111 node *pindex=get_node(index); 112 if (!pindex) 113 { 114 printf("%s failed!\n", __func__); 115 return NULL; 116 } 117 118 return pindex->p; 119 120 } 121 122 // 獲取“雙向鏈表中第1個元素的值” 123 void* dlink_get_first() 124 { 125 return dlink_get(0); 126 } 127 128 // 獲取“雙向鏈表中最后1個元素的值” 129 void* dlink_get_last() 130 { 131 return dlink_get(count-1); 132 } 133 134 // 將“pval”插入到index位置。成功,返回0;否則,返回-1。 135 int dlink_insert(int index, void* pval) 136 { 137 // 插入表頭 138 if (index==0) 139 return dlink_insert_first(pval); 140 141 // 獲取要插入的位置對應的節點 142 node *pindex=get_node(index); 143 if (!pindex) 144 return -1; 145 146 // 創建“節點” 147 node *pnode=create_node(pval); 148 if (!pnode) 149 return -1; 150 151 pnode->prev = pindex->prev; 152 pnode->next = pindex; 153 pindex->prev->next = pnode; 154 pindex->prev = pnode; 155 // 節點個數+1 156 count++; 157 158 return 0; 159 } 160 161 // 將“pval”插入到表頭位置 162 int dlink_insert_first(void *pval) 163 { 164 node *pnode=create_node(pval); 165 if (!pnode) 166 return -1; 167 168 pnode->prev = phead; 169 pnode->next = phead->next; 170 phead->next->prev = pnode; 171 phead->next = pnode; 172 count++; 173 return 0; 174 } 175 176 // 將“pval”插入到末尾位置 177 int dlink_append_last(void *pval) 178 { 179 node *pnode=create_node(pval); 180 if (!pnode) 181 return -1; 182 183 pnode->next = phead; 184 pnode->prev = phead->prev; 185 phead->prev->next = pnode; 186 phead->prev = pnode; 187 count++; 188 return 0; 189 } 190 191 // 刪除“雙向鏈表中index位置的節點”。成功,返回0;否則,返回-1。 192 int dlink_delete(int index) 193 { 194 node *pindex=get_node(index); 195 if (!pindex) 196 { 197 printf("%s failed! the index in out of bound!\n", __func__); 198 return -1; 199 } 200 201 pindex->next->prev = pindex->prev; 202 pindex->prev->next = pindex->next; 203 free(pindex); 204 count--; 205 206 return 0; 207 } 208 209 // 刪除第一個節點 210 int dlink_delete_first() 211 { 212 return dlink_delete(0); 213 } 214 215 // 刪除組后一個節點 216 int dlink_delete_last() 217 { 218 return dlink_delete(count-1); 219 } 220 221 // 撤銷“雙向鏈表”。成功,返回0;否則,返回-1。 222 int destroy_dlink() 223 { 224 if (!phead) 225 { 226 printf("%s failed! dlink is null!\n", __func__); 227 return -1; 228 } 229 230 node *pnode=phead->next; 231 node *ptmp=NULL; 232 while(pnode != phead) 233 { 234 ptmp = pnode; 235 pnode = pnode->next; 236 free(ptmp); 237 } 238 239 free(phead); 240 phead = NULL; 241 count = 0; 242 243 return 0; 244 }
雙向鏈表測試程序(dlink_test.c)
1 #include <stdio.h> 2 #include "double_link.h" 3 4 /** 5 * C 語言實現的雙向鏈表的測試程序。 6 * 7 * (01) int_test() 8 * 演示向雙向鏈表操作“int數據”。 9 * (02) string_test() 10 * 演示向雙向鏈表操作“字符串數據”。 11 * (03) object_test() 12 * 演示向雙向鏈表操作“對象”。 13 * 14 * @author skywang 15 * @date 2013/11/07 16 */ 17 18 // 雙向鏈表操作int數據 19 void int_test() 20 { 21 int iarr[4] = {10, 20, 30, 40}; 22 23 printf("\n----%s----\n", __func__); 24 create_dlink(); // 創建雙向鏈表 25 26 dlink_insert(0, &iarr[0]); // 向雙向鏈表的表頭插入數據 27 dlink_insert(0, &iarr[1]); // 向雙向鏈表的表頭插入數據 28 dlink_insert(0, &iarr[2]); // 向雙向鏈表的表頭插入數據 29 30 printf("dlink_is_empty()=%d\n", dlink_is_empty()); // 雙向鏈表是否為空 31 printf("dlink_size()=%d\n", dlink_size()); // 雙向鏈表的大小 32 33 // 打印雙向鏈表中的全部數據 34 int i; 35 int *p; 36 int sz = dlink_size(); 37 for (i=0; i<sz; i++) 38 { 39 p = (int *)dlink_get(i); 40 printf("dlink_get(%d)=%d\n", i, *p); 41 } 42 43 destroy_dlink(); 44 } 45 46 void string_test() 47 { 48 char* sarr[4] = {"ten", "twenty", "thirty", "forty"}; 49 50 printf("\n----%s----\n", __func__); 51 create_dlink(); // 創建雙向鏈表 52 53 dlink_insert(0, sarr[0]); // 向雙向鏈表的表頭插入數據 54 dlink_insert(0, sarr[1]); // 向雙向鏈表的表頭插入數據 55 dlink_insert(0, sarr[2]); // 向雙向鏈表的表頭插入數據 56 57 printf("dlink_is_empty()=%d\n", dlink_is_empty()); // 雙向鏈表是否為空 58 printf("dlink_size()=%d\n", dlink_size()); // 雙向鏈表的大小 59 60 // 打印雙向鏈表中的全部數據 61 int i; 62 char *p; 63 int sz = dlink_size(); 64 for (i=0; i<sz; i++) 65 { 66 p = (char *)dlink_get(i); 67 printf("dlink_get(%d)=%s\n", i, p); 68 } 69 70 destroy_dlink(); 71 } 72 73 typedef struct tag_stu 74 { 75 int id; 76 char name[20]; 77 }stu; 78 79 static stu arr_stu[] = 80 { 81 {10, "sky"}, 82 {20, "jody"}, 83 {30, "vic"}, 84 {40, "dan"}, 85 }; 86 #define ARR_STU_SIZE ( (sizeof(arr_stu)) / (sizeof(arr_stu[0])) ) 87 88 void object_test() 89 { 90 printf("\n----%s----\n", __func__); 91 create_dlink(); // 創建雙向鏈表 92 93 dlink_insert(0, &arr_stu[0]); // 向雙向鏈表的表頭插入數據 94 dlink_insert(0, &arr_stu[1]); // 向雙向鏈表的表頭插入數據 95 dlink_insert(0, &arr_stu[2]); // 向雙向鏈表的表頭插入數據 96 97 printf("dlink_is_empty()=%d\n", dlink_is_empty()); // 雙向鏈表是否為空 98 printf("dlink_size()=%d\n", dlink_size()); // 雙向鏈表的大小 99 100 // 打印雙向鏈表中的全部數據 101 int i; 102 int sz = dlink_size(); 103 stu *p; 104 for (i=0; i<sz; i++) 105 { 106 p = (stu *)dlink_get(i); 107 printf("dlink_get(%d)=[%d, %s]\n", i, p->id, p->name); 108 } 109 110 destroy_dlink(); 111 } 112 113 int main() 114 { 115 int_test(); // 演示向雙向鏈表操作“int數據”。 116 string_test(); // 演示向雙向鏈表操作“字符串數據”。 117 object_test(); // 演示向雙向鏈表操作“對象”。 118 119 return 0; 120 }
運行結果
----int_test----
dlink_is_empty()=0
dlink_size()=3
dlink_get(0)=30
dlink_get(1)=20
dlink_get(2)=10
----string_test----
dlink_is_empty()=0
dlink_size()=3
dlink_get(0)=thirty
dlink_get(1)=twenty
dlink_get(2)=ten
----object_test----
dlink_is_empty()=0
dlink_size()=3
dlink_get(0)=[30, vic]
dlink_get(1)=[20, jody]
dlink_get(2)=[10, sky]
實現代碼
雙向鏈表文件(DoubleLink.h)
1 #ifndef DOUBLE_LINK_HXX 2 #define DOUBLE_LINK_HXX 3 4 #include <iostream> 5 using namespace std; 6 7 template<class T> 8 struct DNode 9 { 10 public: 11 T value; 12 DNode *prev; 13 DNode *next; 14 public: 15 DNode() { } 16 DNode(T t, DNode *prev, DNode *next) { 17 this->value = t; 18 this->prev = prev; 19 this->next = next; 20 } 21 }; 22 23 template<class T> 24 class DoubleLink 25 { 26 public: 27 DoubleLink(); 28 ~DoubleLink(); 29 30 int size(); 31 int is_empty(); 32 33 T get(int index); 34 T get_first(); 35 T get_last(); 36 37 int insert(int index, T t); 38 int insert_first(T t); 39 int append_last(T t); 40 41 int del(int index); 42 int delete_first(); 43 int delete_last(); 44 45 private: 46 int count; 47 DNode<T> *phead; 48 private: 49 DNode<T> *get_node(int index); 50 }; 51 52 template<class T> 53 DoubleLink<T>::DoubleLink() : count(0) 54 { 55 // 創建“表頭”。注意:表頭沒有存儲數據! 56 phead = new DNode<T>(); 57 phead->prev = phead->next = phead; 58 // 設置鏈表計數為0 59 //count = 0; 60 } 61 62 // 析構函數 63 template<class T> 64 DoubleLink<T>::~DoubleLink() 65 { 66 // 刪除所有的節點 67 DNode<T>* ptmp; 68 DNode<T>* pnode = phead->next; 69 while (pnode != phead) 70 { 71 ptmp = pnode; 72 pnode=pnode->next; 73 delete ptmp; 74 } 75 76 // 刪除"表頭" 77 delete phead; 78 phead = NULL; 79 } 80 81 // 返回節點數目 82 template<class T> 83 int DoubleLink<T>::size() 84 { 85 return count; 86 } 87 88 // 返回鏈表是否為空 89 template<class T> 90 int DoubleLink<T>::is_empty() 91 { 92 return count==0; 93 } 94 95 // 獲取第index位置的節點 96 template<class T> 97 DNode<T>* DoubleLink<T>::get_node(int index) 98 { 99 // 判斷參數有效性 100 if (index<0 || index>=count) 101 { 102 cout << "get node failed! the index in out of bound!" << endl; 103 return NULL; 104 } 105 106 // 正向查找 107 if (index <= count/2) 108 { 109 int i=0; 110 DNode<T>* pindex = phead->next; 111 while (i++ < index) { 112 pindex = pindex->next; 113 } 114 115 return pindex; 116 } 117 118 // 反向查找 119 int j=0; 120 int rindex = count - index -1; 121 DNode<T>* prindex = phead->prev; 122 while (j++ < rindex) { 123 prindex = prindex->prev; 124 } 125 126 return prindex; 127 } 128 129 // 獲取第index位置的節點的值 130 template<class T> 131 T DoubleLink<T>::get(int index) 132 { 133 return get_node(index)->value; 134 } 135 136 // 獲取第1個節點的值 137 template<class T> 138 T DoubleLink<T>::get_first() 139 { 140 return get_node(0)->value; 141 } 142 143 // 獲取最后一個節點的值 144 template<class T> 145 T DoubleLink<T>::get_last() 146 { 147 return get_node(count-1)->value; 148 } 149 150 // 將節點插入到第index位置之前 151 template<class T> 152 int DoubleLink<T>::insert(int index, T t) 153 { 154 if (index == 0) 155 return insert_first(t); 156 157 DNode<T>* pindex = get_node(index); 158 DNode<T>* pnode = new DNode<T>(t, pindex->prev, pindex); 159 pindex->prev->next = pnode; 160 pindex->prev = pnode; 161 count++; 162 163 return 0; 164 } 165 166 // 將節點插入第一個節點處。 167 template<class T> 168 int DoubleLink<T>::insert_first(T t) 169 { 170 DNode<T>* pnode = new DNode<T>(t, phead, phead->next); 171 phead->next->prev = pnode; 172 phead->next = pnode; 173 count++; 174 175 return 0; 176 } 177 178 // 將節點追加到鏈表的末尾 179 template<class T> 180 int DoubleLink<T>::append_last(T t) 181 { 182 DNode<T>* pnode = new DNode<T>(t, phead->prev, phead); 183 phead->prev->next = pnode; 184 phead->prev = pnode; 185 count++; 186 187 return 0; 188 } 189 190 // 刪除index位置的節點 191 template<class T> 192 int DoubleLink<T>::del(int index) 193 { 194 DNode<T>* pindex = get_node(index); 195 pindex->next->prev = pindex->prev; 196 pindex->prev->next = pindex->next; 197 delete pindex; 198 count--; 199 200 return 0; 201 } 202 203 // 刪除第一個節點 204 template<class T> 205 int DoubleLink<T>::delete_first() 206 { 207 return del(0); 208 } 209 210 // 刪除最后一個節點 211 template<class T> 212 int DoubleLink<T>::delete_last() 213 { 214 return del(count-1); 215 } 216 217 #endif
雙向鏈表測試文件(DlinkTest.cpp)
1 #include <iostream> 2 #include "DoubleLink.h" 3 using namespace std; 4 5 // 雙向鏈表操作int數據 6 void int_test() 7 { 8 int iarr[4] = {10, 20, 30, 40}; 9 10 cout << "\n----int_test----" << endl; 11 // 創建雙向鏈表 12 DoubleLink<int>* pdlink = new DoubleLink<int>(); 13 14 pdlink->insert(0, 20); // 將 20 插入到第一個位置 15 pdlink->append_last(10); // 將 10 追加到鏈表末尾 16 pdlink->insert_first(30); // 將 30 插入到第一個位置 17 18 // 雙向鏈表是否為空 19 cout << "is_empty()=" << pdlink->is_empty() <<endl; 20 // 雙向鏈表的大小 21 cout << "size()=" << pdlink->size() <<endl; 22 23 // 打印雙向鏈表中的全部數據 24 int sz = pdlink->size(); 25 for (int i=0; i<sz; i++) 26 cout << "pdlink("<<i<<")=" << pdlink->get(i) <<endl; 27 } 28 29 void string_test() 30 { 31 string sarr[4] = {"ten", "twenty", "thirty", "forty"}; 32 33 cout << "\n----string_test----" << endl; 34 // 創建雙向鏈表 35 DoubleLink<string>* pdlink = new DoubleLink<string>(); 36 37 pdlink->insert(0, sarr[1]); // 將 sarr中第2個元素 插入到第一個位置 38 pdlink->append_last(sarr[0]); // 將 sarr中第1個元素 追加到鏈表末尾 39 pdlink->insert_first(sarr[2]); // 將 sarr中第3個元素 插入到第一個位置 40 41 // 雙向鏈表是否為空 42 cout << "is_empty()=" << pdlink->is_empty() <<endl; 43 // 雙向鏈表的大小 44 cout << "size()=" << pdlink->size() <<endl; 45 46 // 打印雙向鏈表中的全部數據 47 int sz = pdlink->size(); 48 for (int i=0; i<sz; i++) 49 cout << "pdlink("<<i<<")=" << pdlink->get(i) <<endl; 50 } 51 52 struct stu 53 { 54 int id; 55 char name[20]; 56 }; 57 58 static stu arr_stu[] = 59 { 60 {10, "sky"}, 61 {20, "jody"}, 62 {30, "vic"}, 63 {40, "dan"}, 64 }; 65 #define ARR_STU_SIZE ( (sizeof(arr_stu)) / (sizeof(arr_stu[0])) ) 66 67 void object_test() 68 { 69 cout << "\n----object_test----" << endl; 70 // 創建雙向鏈表 71 DoubleLink<stu>* pdlink = new DoubleLink<stu>(); 72 73 pdlink->insert(0, arr_stu[1]); // 將 arr_stu中第2個元素 插入到第一個位置 74 pdlink->append_last(arr_stu[0]); // 將 arr_stu中第1個元素 追加到鏈表末尾 75 pdlink->insert_first(arr_stu[2]); // 將 arr_stu中第3個元素 插入到第一個位置 76 77 // 雙向鏈表是否為空 78 cout << "is_empty()=" << pdlink->is_empty() <<endl; 79 // 雙向鏈表的大小 80 cout << "size()=" << pdlink->size() <<endl; 81 82 // 打印雙向鏈表中的全部數據 83 int sz = pdlink->size(); 84 struct stu p; 85 for (int i=0; i<sz; i++) 86 { 87 p = pdlink->get(i); 88 cout << "pdlink("<<i<<")=[" << p.id << ", " << p.name <<"]" <<endl; 89 } 90 } 91 92 93 int main() 94 { 95 int_test(); // 演示向雙向鏈表操作“int數據”。 96 string_test(); // 演示向雙向鏈表操作“字符串數據”。 97 object_test(); // 演示向雙向鏈表操作“對象”。 98 99 return 0; 100 }
示例說明
在上面的示例中,我將雙向鏈表的"聲明"和"實現"都放在頭文件中。而編程規范告誡我們:將類的聲明和實現分離,在頭文件(.h文件或.hpp)中盡量只包含聲明,而在實現文件(.cpp文件)中負責實現!
那么為什么要這么做呢?這是因為,在雙向鏈表的實現中,采用了模板;而C++編譯器不支持對模板的分離式編譯!簡單點說,如果在DoubleLink.h中聲明,而在DoubleLink.cpp中進行實現的話;當我們在其他類中創建DoubleLink的對象時,會編譯出錯。具體原因,可以參考"為什么C++編譯器不能支持對模板的分離式編譯"。
運行結果
----int_test---- is_empty()=0 size()=3 pdlink(0)=30 pdlink(1)=20 pdlink(2)=10 ----string_test---- is_empty()=0 size()=3 pdlink(0)=thirty pdlink(1)=twenty pdlink(2)=ten ----object_test---- is_empty()=0 size()=3 pdlink(0)=[30, vic] pdlink(1)=[20, jody] pdlink(2)=[10, sky]
實現代碼
雙鏈表類(DoubleLink.java)
1 /** 2 * Java 實現的雙向鏈表。 3 * 注:java自帶的集合包中有實現雙向鏈表,路徑是:java.util.LinkedList 4 * 5 * @author skywang 6 * @date 2013/11/07 7 */ 8 public class DoubleLink<T> { 9 10 // 表頭 11 private DNode<T> mHead; 12 // 節點個數 13 private int mCount; 14 15 // 雙向鏈表“節點”對應的結構體 16 private class DNode<T> { 17 public DNode prev; 18 public DNode next; 19 public T value; 20 21 public DNode(T value, DNode prev, DNode next) { 22 this.value = value; 23 this.prev = prev; 24 this.next = next; 25 } 26 } 27 28 // 構造函數 29 public DoubleLink() { 30 // 創建“表頭”。注意:表頭沒有存儲數據! 31 mHead = new DNode<T>(null, null, null); 32 mHead.prev = mHead.next = mHead; 33 // 初始化“節點個數”為0 34 mCount = 0; 35 } 36 37 // 返回節點數目 38 public int size() { 39 return mCount; 40 } 41 42 // 返回鏈表是否為空 43 public boolean isEmpty() { 44 return mCount==0; 45 } 46 47 // 獲取第index位置的節點 48 private DNode<T> getNode(int index) { 49 if (index<0 || index>=mCount) 50 throw new IndexOutOfBoundsException(); 51 52 // 正向查找 53 if (index <= mCount/2) { 54 DNode<T> node = mHead.next; 55 for (int i=0; i<index; i++) 56 node = node.next; 57 58 return node; 59 } 60 61 // 反向查找 62 DNode<T> rnode = mHead.prev; 63 int rindex = mCount - index -1; 64 for (int j=0; j<rindex; j++) 65 rnode = rnode.prev; 66 67 return rnode; 68 } 69 70 // 獲取第index位置的節點的值 71 public T get(int index) { 72 return getNode(index).value; 73 } 74 75 // 獲取第1個節點的值 76 public T getFirst() { 77 return getNode(0).value; 78 } 79 80 // 獲取最后一個節點的值 81 public T getLast() { 82 return getNode(mCount-1).value; 83 } 84 85 // 將節點插入到第index位置之前 86 public void insert(int index, T t) { 87 if (index==0) { 88 DNode<T> node = new DNode<T>(t, mHead, mHead.next); 89 mHead.next.prev = node; 90 mHead.next = node; 91 mCount++; 92 return ; 93 } 94 95 DNode<T> inode = getNode(index); 96 DNode<T> tnode = new DNode<T>(t, inode.prev, inode); 97 inode.prev.next = tnode; 98 inode.next = tnode; 99 mCount++; 100 return ; 101 } 102 103 // 將節點插入第一個節點處。 104 public void insertFirst(T t) { 105 insert(0, t); 106 } 107 108 // 將節點追加到鏈表的末尾 109 public void appendLast(T t) { 110 DNode<T> node = new DNode<T>(t, mHead.prev, mHead); 111 mHead.prev.next = node; 112 mHead.prev = node; 113 mCount++; 114 } 115 116 // 刪除index位置的節點 117 public void del(int index) { 118 DNode<T> inode = getNode(index); 119 inode.prev.next = inode.next; 120 inode.next.prev = inode.prev; 121 inode = null; 122 mCount--; 123 } 124 125 // 刪除第一個節點 126 public void deleteFirst() { 127 del(0); 128 } 129 130 // 刪除最后一個節點 131 public void deleteLast() { 132 del(mCount-1); 133 } 134 }
測試程序(DlinkTest.java)
1 /** 2 * Java 實現的雙向鏈表。 3 * 注:java自帶的集合包中有實現雙向鏈表,路徑是:java.util.LinkedList 4 * 5 * @author skywang 6 * @date 2013/11/07 7 */ 8 9 public class DlinkTest { 10 11 // 雙向鏈表操作int數據 12 private static void int_test() { 13 int[] iarr = {10, 20, 30, 40}; 14 15 System.out.println("\n----int_test----"); 16 // 創建雙向鏈表 17 DoubleLink<Integer> dlink = new DoubleLink<Integer>(); 18 19 dlink.insert(0, 20); // 將 20 插入到第一個位置 20 dlink.appendLast(10); // 將 10 追加到鏈表末尾 21 dlink.insertFirst(30); // 將 30 插入到第一個位置 22 23 // 雙向鏈表是否為空 24 System.out.printf("isEmpty()=%b\n", dlink.isEmpty()); 25 // 雙向鏈表的大小 26 System.out.printf("size()=%d\n", dlink.size()); 27 28 // 打印出全部的節點 29 for (int i=0; i<dlink.size(); i++) 30 System.out.println("dlink("+i+")="+ dlink.get(i)); 31 } 32 33 34 private static void string_test() { 35 String[] sarr = {"ten", "twenty", "thirty", "forty"}; 36 37 System.out.println("\n----string_test----"); 38 // 創建雙向鏈表 39 DoubleLink<String> dlink = new DoubleLink<String>(); 40 41 dlink.insert(0, sarr[1]); // 將 sarr中第2個元素 插入到第一個位置 42 dlink.appendLast(sarr[0]); // 將 sarr中第1個元素 追加到鏈表末尾 43 dlink.insertFirst(sarr[2]); // 將 sarr中第3個元素 插入到第一個位置 44 45 // 雙向鏈表是否為空 46 System.out.printf("isEmpty()=%b\n", dlink.isEmpty()); 47 // 雙向鏈表的大小 48 System.out.printf("size()=%d\n", dlink.size()); 49 50 // 打印出全部的節點 51 for (int i=0; i<dlink.size(); i++) 52 System.out.println("dlink("+i+")="+ dlink.get(i)); 53 } 54 55 56 // 內部類 57 private static class Student { 58 private int id; 59 private String name; 60 61 public Student(int id, String name) { 62 this.id = id; 63 this.name = name; 64 } 65 66 @Override 67 public String toString() { 68 return "["+id+", "+name+"]"; 69 } 70 } 71 72 private static Student[] students = new Student[]{ 73 new Student(10, "sky"), 74 new Student(20, "jody"), 75 new Student(30, "vic"), 76 new Student(40, "dan"), 77 }; 78 79 private static void object_test() { 80 System.out.println("\n----object_test----"); 81 // 創建雙向鏈表 82 DoubleLink<Student> dlink = new DoubleLink<Student>(); 83 84 dlink.insert(0, students[1]); // 將 students中第2個元素 插入到第一個位置 85 dlink.appendLast(students[0]); // 將 students中第1個元素 追加到鏈表末尾 86 dlink.insertFirst(students[2]); // 將 students中第3個元素 插入到第一個位置 87 88 // 雙向鏈表是否為空 89 System.out.printf("isEmpty()=%b\n", dlink.isEmpty()); 90 // 雙向鏈表的大小 91 System.out.printf("size()=%d\n", dlink.size()); 92 93 // 打印出全部的節點 94 for (int i=0; i<dlink.size(); i++) { 95 System.out.println("dlink("+i+")="+ dlink.get(i)); 96 } 97 } 98 99 100 public static void main(String[] args) { 101 int_test(); // 演示向雙向鏈表操作“int數據”。 102 string_test(); // 演示向雙向鏈表操作“字符串數據”。 103 object_test(); // 演示向雙向鏈表操作“對象”。 104 } 105 }
運行結果
----int_test---- isEmpty()=false size()=3 dlink(0)=30 dlink(1)=20 dlink(2)=10 ----string_test---- isEmpty()=false size()=3 dlink(0)=thirty dlink(1)=twenty dlink(2)=ten ----object_test---- isEmpty()=false size()=3 dlink(0)=[30, vic] dlink(1)=[20, jody] dlink(2)=[10, sky]







