線性表定義:
1、0個或多個元素的集合
2、元素之間是有序的
3、元素個數有限
4、元素數據的類型必須相同
線性表是相同類型的n個數據元素的有限序列。
逐項訪問,順序存儲
前驅 后繼
線性表在程序中表現為一種特殊的數據類型。
線性表的操作則表現為一組函數。
順序表(線性表的順序存儲結構):
SeqList.h
#ifndef _SEQLIST_H_ #define _SEQLIST_H_ typedef void SeqList; typedef void SeqListNode; /* 該方法用於創建並且返回一個空的線性表 */ SeqList* SeqList_Create(int capacity); /* 該方法用於銷毀一個線性表list */ void SeqList_Destroy(SeqList* list); /* 該方法用於將一個線性表list中的所有元素清空 使得線性表回到創建時的初始狀態 */ void SeqList_Clear(SeqList* list); /* 該方法用於返回一個線性表list中的所有元素個數 */ int SeqList_Length(SeqList* list); /* 返回線性表的最大容量 */ int SeqList_Capacity(SeqList* list); /* 該方法用於向一個線性表list的pos位置處插入新元素node 返回值為1表示插入成功,0表示插入失敗 */ int SeqList_Insert(SeqList* list, SeqListNode* node, int pos); /* 該方法用於獲取一個線性表list的pos位置處的元素 返回值為pos位置處的元素,NULL表示獲取失敗 */ SeqListNode* SeqList_Get(SeqList* list, int pos); /* 該方法用於刪除一個線性表list的pos位置處的元素 返回值為被刪除的元素,NULL表示刪除失敗 */ SeqListNode* SeqList_Delete(SeqList* list, int pos); #endif
SeqList.c
#include <stdio.h> #include <malloc.h> #include "SeqList.h" /** 頭文件中定義為void 實現時定義真實的類型 數據封裝 1、對外不用關心list,listNode的真實類型 2、不會產生誤操作 */ typedef unsigned int TSeqListNode; //存儲地址,這樣可以適用於任何數據類型,更通用 typedef struct _tag_SeqList { int capacity; int length; TSeqListNode* node; } TSeqList; SeqList* SeqList_Create(int capacity) // O(1) { TSeqList* ret = NULL; if( capacity >= 0 ) { //結構體本身+數組 ret = (TSeqList*)malloc(sizeof(TSeqList) + sizeof(TSeqListNode) * capacity); } if( ret != NULL ) { ret->capacity = capacity; ret->length = 0; ret->node = (TSeqListNode*)(ret + 1); } return ret; } void SeqList_Destroy(SeqList* list) // O(1) { free(list); } void SeqList_Clear(SeqList* list) // O(1) { TSeqList* sList = (TSeqList*)list; if( sList != NULL ) { sList->length = 0; } } int SeqList_Length(SeqList* list) // O(1) { TSeqList* sList = (TSeqList*)list; int ret = -1; if( sList != NULL ) { ret = sList->length; } return ret; } int SeqList_Capacity(SeqList* list) // O(1) { TSeqList* sList = (TSeqList*)list; int ret = -1; if( sList != NULL ) { ret = sList->capacity; } return ret; } // pos 從0開始算起 int SeqList_Insert(SeqList* list, SeqListNode* node, int pos) // O(n) { TSeqList* sList = (TSeqList*)list; int ret = (sList != NULL); int i = 0; ret = ret && (sList->length + 1 <= sList->capacity); ret = ret && (0 <= pos); if( ret ) { if( pos >= sList->length ) { pos = sList->length; } for(i=sList->length; i>pos; i--) { sList->node[i] = sList->node[i-1]; } sList->node[i] = (TSeqListNode)node; sList->length++; } return ret; } SeqListNode* SeqList_Get(SeqList* list, int pos) // O(1) { TSeqList* sList = (TSeqList*)list; SeqListNode* ret = NULL; if( (sList != NULL) && (0 <= pos) && (pos < sList->length) ) { ret = (SeqListNode*)(sList->node[pos]); } return ret; } SeqListNode* SeqList_Delete(SeqList* list, int pos) // O(n) { TSeqList* sList = (TSeqList*)list; SeqListNode* ret = SeqList_Get(list, pos); int i = 0; if( ret != NULL ) { for(i=pos+1; i<sList->length; i++) { sList->node[i-1] = sList->node[i]; } sList->length--; } return ret; }
main.c
#include <stdio.h> #include <stdlib.h> #include "SeqList.h" /* run this program using the console pauser or add your own getch, system("pause") or input loop */ int main(int argc, char *argv[]) { SeqList* list = SeqList_Create(5); int i = 0; int j = 1; int k = 2; int x = 3; int y = 4; int z = 5; int index = 0; /** 找不到 TSeqList 因為在 SeqList.c 中定義 TSeqList *a = (TSeqList*)list; a->length = 0; */ // 由於list是void*類型,所以不被允許,更加安全 // list->length = 0; SeqList_Insert(list, &i, 0); SeqList_Insert(list, &j, 0); SeqList_Insert(list, &k, 0); SeqList_Insert(list, &x, 0); SeqList_Insert(list, &y, 0); SeqList_Insert(list, &z, 0); for(index=0; index<SeqList_Length(list); index++) { int* p = (int*)SeqList_Get(list, index); printf("%d\n", *p); } printf("\n"); while( SeqList_Length(list) > 0 ) { int* p = (int*)SeqList_Delete(list, 0); printf("%d\n", *p); } SeqList_Destroy(list); return 0; }
優點:
無需為線性表中的邏輯關系增加額外的空間
可以快速獲取表中合法位置的元素
缺點:
插入和刪除需要移動大量的元素。
當線性表長度變化較大時難以確定存儲空間的容量(浪費空間)。
單鏈表(線性表的鏈式存儲)
鏈式存儲定義:
為了表示每個數據元素與其后繼元素之間的邏輯關系,每個元素除了存儲本身的信息外,
還需要存儲其直接后續信息。
節點:數據域+指針域
n個節點鏈接成一個鏈式線性表的結構叫做鏈表。
當每個節點只包含一個指針域時,叫做單鏈表。
表頭節點:
鏈表中第一個節點(但不是數據元素), 包含指向第一個數據元素的指針以及鏈表的一些自身信息.
數據節點:
鏈表中代表數據元素的節點, 包含指向下一個數據元素的指針和數據元素的信息。
尾節點:
鏈表中最后一個數據節點, 其下一元素指針為空,表示無后繼.
頭插法:每次都從鏈表頭部插入
尾插法:每次都從鏈表尾部插入
LinkList.c
#include <stdio.h> #include <malloc.h> #include "LinkList.h" typedef struct _tag_LinkList { LinkListNode header; int length; } TLinkList; LinkList* LinkList_Create() // O(1) { TLinkList* ret = (TLinkList*)malloc(sizeof(TLinkList)); if( ret != NULL ) { ret->length = 0; ret->header.next = NULL; } return ret; } void LinkList_Destroy(LinkList* list) // O(1) { free(list); } void LinkList_Clear(LinkList* list) // O(1) { TLinkList* sList = (TLinkList*)list; if( sList != NULL ) { sList->length = 0; sList->header.next = NULL; } } int LinkList_Length(LinkList* list) // O(1) { TLinkList* sList = (TLinkList*)list; int ret = -1; if( sList != NULL ) { ret = sList->length; } return ret; } int LinkList_Insert(LinkList* list, LinkListNode* node, int pos) // O(n) { TLinkList* sList = (TLinkList*)list; int ret = (sList != NULL) && (pos >= 0) && (node != NULL); int i = 0; if( ret ) { LinkListNode* current = (LinkListNode*)sList; for(i=0; (i<pos) && (current->next != NULL); i++) { current = current->next; } node->next = current->next; current->next = node; sList->length++; } return ret; } LinkListNode* LinkList_Get(LinkList* list, int pos) // O(n) { TLinkList* sList = (TLinkList*)list; //轉換成不同的類型,則可以訪問不同的數據 LinkListNode* ret = NULL; int i = 0; if( (sList != NULL) && (0 <= pos) && (pos < sList->length) ) { //轉換成不同的類型,則可以訪問不同的數據 LinkListNode* current = (LinkListNode*)sList; for(i=0; i<pos; i++) { current = current->next; } ret = current->next; } return ret; } LinkListNode* LinkList_Delete(LinkList* list, int pos) // O(n) { TLinkList* sList = (TLinkList*)list; LinkListNode* ret = NULL; int i = 0; if( (sList != NULL) && (0 <= pos) && (pos < sList->length) ) { LinkListNode* current = (LinkListNode*)sList; for(i=0; i<pos; i++) { current = current->next; } ret = current->next; current->next = ret->next; sList->length--; } return ret; }
LinkList.h
#ifndef _LINKLIST_H_ #define _LINKLIST_H_ typedef void LinkList; typedef struct _tag_LinkListNode LinkListNode; struct _tag_LinkListNode { LinkListNode* next; }; LinkList* LinkList_Create(); void LinkList_Destroy(LinkList* list); void LinkList_Clear(LinkList* list); int LinkList_Length(LinkList* list); int LinkList_Insert(LinkList* list, LinkListNode* node, int pos); LinkListNode* LinkList_Get(LinkList* list, int pos); LinkListNode* LinkList_Delete(LinkList* list, int pos); #endif
main.c
#include <stdio.h> #include <stdlib.h> #include "LinkList.h" /* run this program using the console pauser or add your own getch, system("pause") or input loop */ struct Value { LinkListNode header; int v; }; int main(int argc, char *argv[]) { int i = 0; LinkList* list = LinkList_Create(); struct Value v1; struct Value v2; struct Value v3; struct Value v4; struct Value v5; v1.v = 1; v2.v = 2; v3.v = 3; v4.v = 4; v5.v = 5; //尾插法建立鏈表 LinkList_Insert(list, (LinkListNode*)&v1, LinkList_Length(list)); LinkList_Insert(list, (LinkListNode*)&v2, LinkList_Length(list)); LinkList_Insert(list, (LinkListNode*)&v3, LinkList_Length(list)); LinkList_Insert(list, (LinkListNode*)&v4, LinkList_Length(list)); LinkList_Insert(list, (LinkListNode*)&v5, LinkList_Length(list)); for(i=0; i<LinkList_Length(list); i++) { struct Value* pv = (struct Value*)LinkList_Get(list, i); printf("%d\n", pv->v); } while( LinkList_Length(list) > 0 ) { struct Value* pv = (struct Value*)LinkList_Delete(list, 0); printf("%d\n", pv->v); } LinkList_Destroy(list); return 0; }
優點:
無需一次性定制鏈表的容量。
插入和刪除無需移動數據元素。
缺點:
數據元素必須保存后繼元素的位置信息。
獲取指定的數據元素操作需要順序訪問之前的元素。
單鏈表必須包含一個額外的指針域,沒有指針的程序無法實現。(有些語言沒有指針)
靜態鏈表(單鏈表的數組方式實現)
靜態鏈表是順序表的改進,解決了順序表插入和刪除要移動大量元素的問題,同時解決了單鏈表必須依靠指針的問題。
靜態鏈表(在順序表的基礎上用數組實現的單鏈表):
順序表中的元素由兩個元素組成:data和next
data用於存儲數據。
next用於存儲下一個元素在數組中的下標。
靜態鏈表主要用於不支持指針的程序數據語言。
靜態鏈表的實現是一種內存管理的有簡易方法。(類似 malloc, free功能)
StaticList.h
#ifndef _STATICLIST_H_ #define _STATICLIST_H_ typedef void StaticList; typedef void StaticListNode; StaticList* StaticList_Create(int capacity); void StaticList_Destroy(StaticList* list); void StaticList_Clear(StaticList* list); int StaticList_Length(StaticList* list); int StaticList_Capacity(StaticList* list); int StaticList_Insert(StaticList* list, StaticListNode* node, int pos); StaticListNode* StaticList_Get(StaticList* list, int pos); StaticListNode* StaticList_Delete(StaticList* list, int pos); #endif
StaticList.c
#include <stdio.h> #include <malloc.h> #include "StaticList.h" #define AVAILABLE -1 typedef struct _tag_StaticListNode { unsigned int data; int next; //數組下標 } TStaticListNode; typedef struct _tag_StaticList { int capacity; TStaticListNode header; // 下面數組的第一個元素 TStaticListNode node[]; } TStaticList; StaticList* StaticList_Create(int capacity) // O(n) { TStaticList* ret = NULL; int i = 0; if( capacity >= 0 ) { ret = (TStaticList*)malloc(sizeof(TStaticList) + sizeof(TStaticListNode) * (capacity + 1)); } if( ret != NULL ) { ret->capacity = capacity; ret->header.data = 0; // length, 復用頭結點 ret->header.next = 0; for(i=1; i<=capacity; i++) { ret->node[i].next = AVAILABLE; } } return ret; } void StaticList_Destroy(StaticList* list) // O(1) { free(list); } void StaticList_Clear(StaticList* list) // O(n) { TStaticList* sList = (TStaticList*)list; int i = 0; if( sList != NULL ) { sList->header.data = 0; sList->header.next = 0; for(i=1; i<=sList->capacity; i++) { sList->node[i].next = AVAILABLE; } } } int StaticList_Length(StaticList* list) // O(1) { TStaticList* sList = (TStaticList*)list; int ret = -1; if( sList != NULL ) { ret = sList->header.data; } return ret; } int StaticList_Capacity(StaticList* list) // O(1) { TStaticList* sList = (TStaticList*)list; int ret = -1; if( sList != NULL ) { ret = sList->capacity; } return ret; } int StaticList_Insert(StaticList* list, StaticListNode* node, int pos) // O(n) { TStaticList* sList = (TStaticList*)list; int ret = (sList != NULL); int current = 0; int index = 0; // 可利用下標 int i = 0; ret = ret && (sList->header.data + 1 <= sList->capacity); ret = ret && (pos >=0) && (node != NULL); if( ret ) { // 尋找可以利用的位置 for(i=1; i<=sList->capacity; i++) { if( sList->node[i].next == AVAILABLE ) { index = i; break; } } sList->node[index].data = (unsigned int)node; sList->node[0] = sList->header; for(i=0; (i<pos) && (sList->node[current].next != 0); i++) { current = sList->node[current].next; } sList->node[index].next = sList->node[current].next; sList->node[current].next = index; sList->node[0].data++; sList->header = sList->node[0]; } return ret; } StaticListNode* StaticList_Get(StaticList* list, int pos) // O(n) { TStaticList* sList = (TStaticList*)list; StaticListNode* ret = NULL; int current = 0; int object = 0; int i = 0; if( (sList != NULL) && (0 <= pos) && (pos < sList->header.data) ) { sList->node[0] = sList->header; for(i=0; i<pos; i++) { current = sList->node[current].next; } object = sList->node[current].next; ret = (StaticListNode*)(sList->node[object].data); } return ret; } StaticListNode* StaticList_Delete(StaticList* list, int pos) // O(n) { TStaticList* sList = (TStaticList*)list; StaticListNode* ret = NULL; int current = 0; int object = 0; int i = 0; if( (sList != NULL) && (0 <= pos) && (pos < sList->header.data) ) { sList->node[0] = sList->header; for(i=0; i<pos; i++) { current = sList->node[current].next; } object = sList->node[current].next; sList->node[current].next = sList->node[object].next; sList->node[0].data--; sList->header = sList->node[0]; sList->node[object].next = AVAILABLE; ret = (StaticListNode*)(sList->node[object].data); } return ret; }
main.c
#include <stdio.h> #include <stdlib.h> #include "StaticList.h" /* run this program using the console pauser or add your own getch, system("pause") or input loop */ int main(int argc, char *argv[]) { StaticList* list = StaticList_Create(10); int index = 0; int i = 0; int j = 1; int k = 2; int x = 3; int y = 4; int z = 5; StaticList_Insert(list, &i, 0); StaticList_Insert(list, &j, 0); StaticList_Insert(list, &k, 0); for(index=0; index<StaticList_Length(list); index++) { int* p = (int*)StaticList_Get(list, index); printf("%d\n", *p); } printf("\n"); while( StaticList_Length(list) > 0 ) { int* p = (int*)StaticList_Delete(list, 0); printf("%d\n", *p); } printf("\n"); StaticList_Insert(list, &x, 0); StaticList_Insert(list, &y, 0); StaticList_Insert(list, &z, 0); printf("Capacity: %d Length: %d\n", StaticList_Capacity(list), StaticList_Length(list)); for(index=0; index<StaticList_Length(list); index++) { int* p = (int*)StaticList_Get(list, index); printf("%d\n", *p); } StaticList_Destroy(list); return 0; }
循環鏈表(單鏈表的擴展)
CircleList.h
#ifndef _CIRCLELIST_H_ #define _CIRCLELIST_H_ typedef void CircleList; typedef struct _tag_CircleListNode CircleListNode; struct _tag_CircleListNode { CircleListNode* next; }; CircleList* CircleList_Create(); void CircleList_Destroy(CircleList* list); void CircleList_Clear(CircleList* list); int CircleList_Length(CircleList* list); int CircleList_Insert(CircleList* list, CircleListNode* node, int pos); CircleListNode* CircleList_Get(CircleList* list, int pos); CircleListNode* CircleList_Delete(CircleList* list, int pos); CircleListNode* CircleList_DeleteNode(CircleList* list, CircleListNode* node); CircleListNode* CircleList_Reset(CircleList* list); CircleListNode* CircleList_Current(CircleList* list); CircleListNode* CircleList_Next(CircleList* list); #endif
CircleList.c
#include <stdio.h> #include <malloc.h> #include "CircleList.h" typedef struct _tag_CircleList { CircleListNode header; CircleListNode* slider; //游標 int length; } TCircleList; CircleList* CircleList_Create() // O(1) { TCircleList* ret = (TCircleList*)malloc(sizeof(TCircleList)); if( ret != NULL ) { ret->length = 0; ret->header.next = NULL; ret->slider = NULL; } return ret; } void CircleList_Destroy(CircleList* list) // O(1) { free(list); } void CircleList_Clear(CircleList* list) // O(1) { TCircleList* sList = (TCircleList*)list; if( sList != NULL ) { sList->length = 0; sList->header.next = NULL; sList->slider = NULL; } } int CircleList_Length(CircleList* list) // O(1) { TCircleList* sList = (TCircleList*)list; int ret = -1; if( sList != NULL ) { ret = sList->length; } return ret; } int CircleList_Insert(CircleList* list, CircleListNode* node, int pos) // O(n) 注: n並非鏈表的長度,而是插入的位置 { TCircleList* sList = (TCircleList*)list; int ret = (sList != NULL) && (pos >= 0) && (node != NULL); int i = 0; if( ret ) { CircleListNode* current = (CircleListNode*)sList; for(i=0; (i<pos) && (current->next != NULL); i++) { current = current->next; } node->next = current->next; current->next = node; //特殊判斷 構成環 if( sList->length == 0 ) { sList->slider = node; // 游標默認指向第一個元素 } //特殊判斷
if( current == (CircleListNode*)sList )//如果插入的是第一個元素,尾節點要指向新插入的元素
{
CircleListNode* last = CircleList_Get(sList, sList->length - 1);
last->next = current->next;
}
sList->length++; } return ret; } CircleListNode* CircleList_Get(CircleList* list, int pos) // O(n) { TCircleList* sList = (TCircleList*)list; CircleListNode* ret = NULL; int i = 0; if( (sList != NULL) && (pos >= 0) /* 可以轉圈 */ ) { CircleListNode* current = (CircleListNode*)sList; for(i=0; i<pos; i++) { current = current->next; } ret = current->next; } return ret; } CircleListNode* CircleList_Delete(CircleList* list, int pos) // O(n) { TCircleList* sList = (TCircleList*)list; CircleListNode* ret = NULL; int i = 0; if( (sList != NULL) && (pos >= 0) && ( sList->length>0)) { CircleListNode* current = (CircleListNode*)sList; CircleListNode* first = sList->header.next; CircleListNode* last = (CircleListNode*)CircleList_Get(sList, sList->length - 1); for(i=0; i<pos; i++) { current = current->next; } ret = current->next; current->next = ret->next; sList->length--; //刪除首元素時 if( first == ret ) { // sList->header.next = ret->next; // @todo last->next = ret->next; // @oops 刪除首元素時必須要手動處理環 } if( sList->slider == ret ) { sList->slider = ret->next; } if( sList->length == 0 ) //@oops { sList->header.next = NULL; //鏈表變空時要手動 置為 null, 因為現在是環狀,不會存在null值 sList->slider = NULL; } } return ret; } CircleListNode* CircleList_DeleteNode(CircleList* list, CircleListNode* node) // O(n) { TCircleList* sList = (TCircleList*)list; CircleListNode* ret = NULL; int i = 0; if( sList != NULL ) { CircleListNode* current = (CircleListNode*)sList; for(i=0; i<sList->length; i++) { if( current->next == node ) { ret = current->next; break; } current = current->next; } if( ret != NULL ) { CircleList_Delete(sList, i); } } return ret; } CircleListNode* CircleList_Reset(CircleList* list) // O(1) { TCircleList* sList = (TCircleList*)list; CircleListNode* ret = NULL; if( sList != NULL ) { sList->slider = sList->header.next; ret = sList->slider; } return ret; } CircleListNode* CircleList_Current(CircleList* list) // O(1) { TCircleList* sList = (TCircleList*)list; CircleListNode* ret = NULL; if( sList != NULL ) { ret = sList->slider; } return ret; } CircleListNode* CircleList_Next(CircleList* list) // O(1) { TCircleList* sList = (TCircleList*)list; CircleListNode* ret = NULL; if( (sList != NULL) && (sList->slider != NULL) ) { ret = sList->slider; sList->slider = ret->next; } return ret; }
main.c
#include <stdio.h> #include <stdlib.h> #include "CircleList.h" /* run this program using the console pauser or add your own getch, system("pause") or input loop */ struct Value { CircleListNode header; int v; }; int main(int argc, char *argv[]) { int i = 0; CircleList* list = CircleList_Create(); struct Value v1; struct Value v2; struct Value v3; struct Value v4; struct Value v5; struct Value v6; struct Value v7; struct Value v8; v1.v = 1; v2.v = 2; v3.v = 3; v4.v = 4; v5.v = 5; v6.v = 6; v7.v = 7; v8.v = 8; CircleList_Insert(list, (CircleListNode*)&v1, CircleList_Length(list)); CircleList_Insert(list, (CircleListNode*)&v2, CircleList_Length(list)); CircleList_Insert(list, (CircleListNode*)&v3, CircleList_Length(list)); CircleList_Insert(list, (CircleListNode*)&v4, CircleList_Length(list)); CircleList_Insert(list, (CircleListNode*)&v5, 5); CircleList_Delete(list, 0); for(i=0; i<2*CircleList_Length(list); i++) { struct Value* pv = (struct Value*)CircleList_Get(list, i); printf("%d\n", pv->v); } printf("\n"); while( CircleList_Length(list) > 0 ) { struct Value* pv = (struct Value*)CircleList_Delete(list, 0); printf("%d\n", pv->v); } CircleList_Destroy(list); return 0; }
循環鏈表是單鏈表基礎上的一個增強,可以完全替代單鏈表。
循環鏈表的next和current操作可以高效的遍歷鏈表中的所有元素。
雙向鏈表:
單鏈表的數據元素無法直接訪問其前驅元素。
逆序訪問單鏈表的元素是極其耗時的。
雙向鏈表的定義:
在單鏈表節點中增加一個指向其前驅的pre指針
DLinkList.h
#ifndef _DLINKLIST_H_ #define _DLINKLIST_H_ typedef void DLinkList; typedef struct _tag_DLinkListNode DLinkListNode; struct _tag_DLinkListNode { DLinkListNode* next; DLinkListNode* pre; }; DLinkList* DLinkList_Create(); void DLinkList_Destroy(DLinkList* list); void DLinkList_Clear(DLinkList* list); int DLinkList_Length(DLinkList* list); int DLinkList_Insert(DLinkList* list, DLinkListNode* node, int pos); DLinkListNode* DLinkList_Get(DLinkList* list, int pos); DLinkListNode* DLinkList_Delete(DLinkList* list, int pos); DLinkListNode* DLinkList_DeleteNode(DLinkList* list, DLinkListNode* node); DLinkListNode* DLinkList_Reset(DLinkList* list); DLinkListNode* DLinkList_Current(DLinkList* list); DLinkListNode* DLinkList_Next(DLinkList* list); DLinkListNode* DLinkList_Pre(DLinkList* list); #endif
DLinkList.c
#include <stdio.h> #include <malloc.h> #include "DLinkList.h" typedef struct _tag_DLinkList { DLinkListNode header; DLinkListNode* slider; int length; } TDLinkList; DLinkList* DLinkList_Create() // O(1) { TDLinkList* ret = (TDLinkList*)malloc(sizeof(TDLinkList)); if( ret != NULL ) { ret->length = 0; ret->header.next = NULL; ret->header.pre = NULL; ret->slider = NULL; } return ret; } void DLinkList_Destroy(DLinkList* list) // O(1) { free(list); } void DLinkList_Clear(DLinkList* list) // O(1) { TDLinkList* sList = (TDLinkList*)list; if( sList != NULL ) { sList->length = 0; sList->header.next = NULL; sList->header.pre = NULL; sList->slider = NULL; } } int DLinkList_Length(DLinkList* list) // O(1) { TDLinkList* sList = (TDLinkList*)list; int ret = -1; if( sList != NULL ) { ret = sList->length; } return ret; } int DLinkList_Insert(DLinkList* list, DLinkListNode* node, int pos) // O(n) { TDLinkList* sList = (TDLinkList*)list; int ret = (sList != NULL) && (pos >= 0) && (node != NULL); int i = 0; if( ret ) { DLinkListNode* current = (DLinkListNode*)sList; DLinkListNode* next = NULL; for(i=0; (i<pos) && (current->next != NULL); i++) { current = current->next; } next = current->next; current->next = node; node->next = next; //如果是空鏈表或最后一個元素則next沒有prev if( next != NULL ) { next->pre = node; } node->pre = current; //如果插入的是第一個元素,prev應為 NULL if( sList->length == 0 ) { sList->slider = node; //游標默認指向第一個元素 }
if( current == (CircleListNode*)sList )
{
CircleListNode* last = CircleList_Get(sList, sList->length - 1);
last->next = current->next;
}
sList->length++; } return ret; } DLinkListNode* DLinkList_Get(DLinkList* list, int pos) // O(n) { TDLinkList* sList = (TDLinkList*)list; DLinkListNode* ret = NULL; int i = 0; if( (sList != NULL) && (0 <= pos) && (pos < sList->length) ) { DLinkListNode* current = (DLinkListNode*)sList; for(i=0; i<pos; i++) { current = current->next; } ret = current->next; } return ret; } DLinkListNode* DLinkList_Delete(DLinkList* list, int pos) // O(n) { TDLinkList* sList = (TDLinkList*)list; DLinkListNode* ret = NULL; int i = 0; if( (sList != NULL) && (0 <= pos) && (pos < sList->length) ) { DLinkListNode* current = (DLinkListNode*)sList; DLinkListNode* next = NULL; for(i=0; i<pos; i++) { current = current->next; } ret = current->next; next = ret->next; current->next = next; if( next != NULL )//刪除最后一個元素 { next->pre = current; //刪除第一個元素,第二元素的prev=null if( current == (DLinkListNode*)sList ) { next->pre = NULL; } } if( sList->slider == ret ) { sList->slider = next; } sList->length--; } return ret; } DLinkListNode* DLinkList_DeleteNode(DLinkList* list, DLinkListNode* node) { TDLinkList* sList = (TDLinkList*)list; DLinkListNode* ret = NULL; int i = 0; if( sList != NULL ) { DLinkListNode* current = (DLinkListNode*)sList; for(i=0; i<sList->length; i++) { if( current->next == node ) { ret = current->next; break; } current = current->next; } if( ret != NULL ) { DLinkList_Delete(sList, i); } } return ret; } DLinkListNode* DLinkList_Reset(DLinkList* list) { TDLinkList* sList = (TDLinkList*)list; DLinkListNode* ret = NULL; if( sList != NULL ) { sList->slider = sList->header.next; ret = sList->slider; } return ret; } DLinkListNode* DLinkList_Current(DLinkList* list) { TDLinkList* sList = (TDLinkList*)list; DLinkListNode* ret = NULL; if( sList != NULL ) { ret = sList->slider; } return ret; } DLinkListNode* DLinkList_Next(DLinkList* list) { TDLinkList* sList = (TDLinkList*)list; DLinkListNode* ret = NULL; if( (sList != NULL) && (sList->slider != NULL) ) { ret = sList->slider; sList->slider = ret->next; } return ret; } DLinkListNode* DLinkList_Pre(DLinkList* list) { TDLinkList* sList = (TDLinkList*)list; DLinkListNode* ret = NULL; if( (sList != NULL) && (sList->slider != NULL) ) { ret = sList->slider; sList->slider = ret->pre; } return ret; }
main.c
#include <stdio.h> #include <stdlib.h> #include "DLinkList.h" /* run this program using the console pauser or add your own getch, system("pause") or input loop */ struct Value { DLinkListNode header; int v; }; int main(int argc, char *argv[]) { int i = 0; DLinkList* list = DLinkList_Create(); struct Value* pv = NULL; struct Value v1; struct Value v2; struct Value v3; struct Value v4; struct Value v5; v1.v = 1; v2.v = 2; v3.v = 3; v4.v = 4; v5.v = 5; DLinkList_Insert(list, (DLinkListNode*)&v1, DLinkList_Length(list)); DLinkList_Insert(list, (DLinkListNode*)&v2, DLinkList_Length(list)); DLinkList_Insert(list, (DLinkListNode*)&v3, DLinkList_Length(list)); DLinkList_Insert(list, (DLinkListNode*)&v4, DLinkList_Length(list)); DLinkList_Insert(list, (DLinkListNode*)&v5, DLinkList_Length(list)); for(i=0; i<DLinkList_Length(list); i++) { pv = (struct Value*)DLinkList_Get(list, i); printf("%d\n", pv->v); } printf("\n"); DLinkList_Delete(list, DLinkList_Length(list)-1); DLinkList_Delete(list, 0); for(i=0; i<DLinkList_Length(list); i++) { pv = (struct Value*)DLinkList_Next(list); printf("%d\n", pv->v); } printf("\n"); DLinkList_Reset(list); DLinkList_Next(list); pv = (struct Value*)DLinkList_Current(list); printf("%d\n", pv->v); DLinkList_DeleteNode(list, (DLinkListNode*)pv); pv = (struct Value*)DLinkList_Current(list); printf("%d\n", pv->v); DLinkList_Pre(list); pv = (struct Value*)DLinkList_Current(list); printf("%d\n", pv->v); printf("Length: %d\n", DLinkList_Length(list)); DLinkList_Destroy(list); return 0; }