线性表的本质
有時(shí)候就會(huì)有一種感覺,盡管學(xué)習(xí)了C和C++,看到程序都差不多看得懂,但是真正讓自己去開發(fā)一個(gè)軟件或者獨(dú)立性的去寫一些代碼的時(shí)候還是很困難,我們都知道程序的靈魂是算法,一個(gè)程序是算法和數(shù)據(jù)結(jié)構(gòu)的相結(jié)合,在接下來來的寒假時(shí)光中,筆者將會(huì)學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)的一些基礎(chǔ)知識(shí),并且加上個(gè)人的一些理解,和大家一起分享。
下面我將從4個(gè)方面介紹線性表的基本和常用知識(shí)。線性表的本質(zhì),線性表的相關(guān)操作,線性表的順序存儲(chǔ)結(jié)構(gòu),線性表鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)。
一個(gè)線性表是是n個(gè)數(shù)據(jù)元素的有限序列,有以下定義:
線性表是零個(gè)或者多個(gè)數(shù)據(jù)元素的集合
線性表中的數(shù)據(jù)之間是有順序的
線性表中的數(shù)據(jù)元素是有限的
線性表中的數(shù)據(jù)元素的類型必須相同
線性表的一些常用操作:
List* List_Create(); //創(chuàng)建線性表
void List_Destrory(List* list); //銷毀線性表
void List_Clear(List* list); //清空線性表
int List_Insert(List* list,ListNode* node,int pos); //將元素插入線性表
ListNode* List_Delete(List* list,int pos); //將元素在線性表中刪除
ListNode* List_Get(List* list,int pos); //獲取線性表中的某個(gè)位置的元素
int List_Length(List* list); //獲取線性表的長度
這些都是線性表的一些基礎(chǔ)知識(shí),線性表還有好些操作,當(dāng)然相關(guān)命名也是可以變得 ,在后面的線性表的順序存儲(chǔ)結(jié)構(gòu)和線性表鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)中會(huì)運(yùn)用到這些,下面來介紹一下線性表的順序存儲(chǔ)結(jié)構(gòu)。
順序存儲(chǔ)結(jié)構(gòu),指的是用一段地址連續(xù)的存儲(chǔ)單元依次存儲(chǔ)線性表的數(shù)據(jù)元素。
在C語言中,可以用一維數(shù)組來實(shí)現(xiàn)順序存儲(chǔ)結(jié)構(gòu)。存儲(chǔ)空間的起始位置:數(shù)組node;線性表的最大容量:數(shù)組長度MAXSIZE;線性表的當(dāng)前長度:length。。可表示如下:
1 #define MAXSIZE 20 2 3 typedef struct _tag_List 4 5 { 6 7 char node[MAXSIZE]; 8 9 int length; 10 11 } List;獲取元素操作算法如下:
1 char Get(List* list,int pos) 2 { 3 cahr ret = -1; 4 5 //判斷線性表是否合法 6 //判斷位置是否合法 7 8 if((List != NULL) && (0 <= pos) && (pos < list -> length)) 9 { 10 //獲取元素 11 ret = list -> node[pos]; 12 } 13 return ret; 14 }插入元素算法:
1 int Insert(List* list,cahr c,int pos) 2 { 3 //判斷線性表是否合法 4 int ret = (list != NULL); 5 int i = 0; 6 7 //判斷插入位置是否合法 8 ret = ret && (list -> length + 1 <= MAXSIZE); 9 ret = ret && (0 <= pos); 10 11 if( ret ) 12 { 13 if( pos >= list -> length ) 14 { 15 pos = list -> length; 16 } 17 18 //從最后一個(gè)元素開始到第pos個(gè)位置 19 //分別將他們都向后移動(dòng)一個(gè)位置 20 for( i = list -> length;i>pos;i-- ) 21 { 22 list -> node[i] = list -> node[i-1]; 23 } 24 25 //將新元素插入 26 list -> node[i] = c; 27 28 //長度加1 29 list -> length++; 30 } 31 32 return ret; 33 }刪除元素算法:
1 char Delete(List* list,int pos) 2 { 3 char ret = -1; 4 int i = 0; 5 6 //判斷線性表是否合法 7 //判斷刪除位置是都合法 8 if( (list != NULL) && (0 <= pos) && (pos < list -> length) ) 9 { 10 //取出刪除元素 11 ret = list -> node[pos]; 12 13 //把刪除位置pos后的元素分別向前移動(dòng)一個(gè)位置 14 for( int i = pos + 1;i < list -> length;i++) 15 { 16 list -> node[i-1] = list -> node[i]; 17 } 18 19 //長度減1 20 list -> length--; 21 } 22 23 return ret; 24 }這種方法無需為線性表中的邏輯關(guān)系增加額外的空間,可以快速的獲取表中合法位置的元素,但是插入和刪除元素的草種需要移動(dòng)大量的元素,當(dāng)線性表長度變化較大時(shí)難以確定存儲(chǔ)空間的容量。
為了表示每個(gè)元素與其直接后繼元素之間的邏輯關(guān)系,每個(gè)元素除了本身的信息之外,還需要存儲(chǔ)指示其直接后繼的信息,這就是鏈?zhǔn)酱鎯?chǔ)。
在C語言中可以用結(jié)構(gòu)體來定義鏈表中的指針域,鏈表中的表頭結(jié)點(diǎn)也可以用結(jié)構(gòu)體來實(shí)現(xiàn),代碼如下:
結(jié)點(diǎn)指針域定義1 typedef struct _tag_LinkListNode LinkListNode 2 struct _tag_LinkListNode 3 { 4 LinkListNode* next; 5 }; 1 頭結(jié)點(diǎn)定義 2 typedef struct _tag_LinkList 3 { 4 LinkListNode header; 5 int length; 6 } TLinkList; 數(shù)據(jù)元素定義示例 struct Value {LinkListNode header;int v; };
獲取第pos個(gè)元素操作
1 LinkListNode* current = (LinkListNode*) list; 2 //判斷線性表是否合法 3 //判斷位置是否合法 4 5 for (i = 0;i<pos;i++) 6 { 7 //由表頭開始通過next指針移動(dòng)pos次后,當(dāng)前元素的next指針即指 向要獲取的元素 8 current = current -> next; 9 } 10 11 ret = current -> next;插入元素到位置pos的算法
1 LinkLinkNode* current = (LinkListNode*) list; 2 //判斷線性表是否合法 3 //判斷插入位置是否合法 4 for(i = 0;(i < pos) && (current -> next != NULL);i++) 5 { 6 //由表頭看似hi通過next指針移動(dòng)pos次后,當(dāng)前元素的next指針即指向要插入的位置 7 current = current -> next; 8 } 9 //將新元素插入 10 node -> next = current -> next; 11 current -> next = node; 12 //線性表長度加1 13 sList -> length++;刪除第pos個(gè)元素的算法
1 TLinkkList* sList = (TLinkList*)list; 2 //判斷線性表是否合法 3 //判斷插入位置是否合法 4 5 LinkListNode* ret = NuLL; 6 int i = 0; 7 //獲取第pos個(gè)元素 8 if((sList != NULL) && (0 <= pos) && (pos <sList -> length)) 9 { 10 LinkListNode* current = (LinkListNode*)list; 11 12 for( i = 0;i < pos;i++ ) 13 { 14 current = current ->next; 15 } 16 //將第pos個(gè)元素從鏈表中刪除 17 ret = current -> next; 18 current ->next = ret ->next; 19 //線性表長度減1 20 sList -> length--; 21 }鏈?zhǔn)浇Y(jié)構(gòu)無需一次性定制鏈表的容量并且插入和刪除操作無需移動(dòng)數(shù)據(jù)元素,但是數(shù)據(jù)元素必須保存后繼元素的位置信息,獲取指定數(shù)據(jù)的元素操作需要順序訪問之前的元素。
?
總結(jié)
- 上一篇: Akka Types of dispat
- 下一篇: Android客户端实现七牛云存储文件上