单链表的结点都只有一个指向下一个结点的指针 单链表的数据元素无法直接访问其前驱元素 逆序访问单链表中的元素是极其耗时的操作! |
len = LinkList_Length(list); for (i=len-1; len>=0; i++) //O(n) { LinkListNode *p = LinkList_Get(list, i); //O(n) //访问数据元素p中的元素 // } |
双向链表的定义 在单链表的结点中增加一个指向其前驱的pre指针 |
插入操作异常处理 插入第一个元素异常处理 在0号位置处插入元素; |
删除操作 |
删除操作异常处理 |
双向链表的新操作 |
获取当前游标指向的数据元素 将游标重置指向链表中的第一个数据元素 将游标移动指向到链表中的下一个数据元素 将游标移动指向到链表中的上一个数据元素 直接指定删除链表中的某个数据元素 |
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); |
循环链表插入结点技术场景
循环链表删除结点技术场景
优点和缺点
优点:双向链表在单链表的基础上增加了指向前驱的指针 功能上双向链表可以完全取代单链表的使用 双向链表的Next,Pre和Current操作可以高效的遍历链表中的所有元素 |
缺点:代码复杂 |
02 08 10
#ifndef _MY_DLINKLIST_H_ #define _MY_DLINKLIST_H_ typedef void DLinkList; /* typedef struct _tag_DLinkListNode DLinkListNode; struct _tag_DLinkListNode { DLinkListNode* next; DLinkListNode* pre; }; */ typedef struct _tag_DLinkListNode { struct _tag_DLinkListNode* next; struct _tag_DLinkListNode * pre; }DLinkListNode; 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); //-- add 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
#include <stdio.h> #include <malloc.h> #include "DLinkList.h" typedef struct _tag_DLinkList { DLinkListNode header; DLinkListNode* slider; int length; } TDLinkList; DLinkList* DLinkList_Create() { 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) { if (list != NULL) { free(list); } } void DLinkList_Clear(DLinkList* list) { 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) { TDLinkList* sList = (TDLinkList*)list; int ret = -1; if( sList != NULL ) { ret = sList->length; } return ret; } //大家一定要注意:教科书不会告诉你 项目上如何用;哪些点是项目的重点 int DLinkList_Insert(DLinkList* list, DLinkListNode* node, int pos) { int ret = 0, i = 0; TDLinkList* sList = (TDLinkList*)list; if (list==NULL || node==NULL || pos<0) { return -1; } DLinkListNode* current = (DLinkListNode*)sList; DLinkListNode* next = NULL; //需要增加next指针 for(i=0; (i<pos) && (current->next != NULL); i++) { current = current->next; } next = current->next; //步骤1-2 current->next = node; node->next = next; //步骤3-4 if( next != NULL ) //当链表插入第一个元素,需要特殊处理 { next->pre = node; } node->pre = current; if( sList->length == 0 ) { sList->slider = node; //当链表插入第一个元素处理游标 } //若在0位置插入,需要特殊处理 新来结点next前pre指向null if( current == (DLinkListNode*)sList ) { node->pre = NULL; } sList->length++; return ret; } DLinkListNode* DLinkList_Get(DLinkList* list, int pos) { 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) { TDLinkList* sList = (TDLinkList*)list; DLinkListNode* ret = NULL; int i = 0; if (sList == NULL || pos <0 ) { return NULL; } //if( (sList != NULL) && (0 <= pos) && (pos < sList->length) ) { DLinkListNode* current = (DLinkListNode*)sList; DLinkListNode* next = NULL; //需要增加next指针 for(i=0; i<pos; i++) { current = current->next; } ret = current->next; next = ret->next; //步骤1 current->next = next; //步骤2 if( next != NULL )//需要特殊处理 { next->pre = current; if( current == (DLinkListNode*)sList ) //若第0个位置,需要特殊处理 { 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; }
#include <stdio.h> #include <stdlib.h> #include "DLinkList.h" struct Value { DLinkListNode node; int v; }; int main() { int i = 0; DLinkList* list = DLinkList_Create(); struct Value* pv = NULL; struct Value v1, v2, v3, v4, 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 ", pv->v); } printf(" "); DLinkList_Delete(list, DLinkList_Length(list)-1); DLinkList_Delete(list, 0); //DLinkList_Delete(list, 3); for(i=0; i<DLinkList_Length(list); i++) { pv = (struct Value*)DLinkList_Next(list); printf("%d ", pv->v); } printf(" "); DLinkList_Reset(list); DLinkList_Next(list); pv = (struct Value*)DLinkList_Current(list); printf("%d ", pv->v); DLinkList_DeleteNode(list, (DLinkListNode*)pv); pv = (struct Value*)DLinkList_Current(list); printf("%d ", pv->v); DLinkList_Pre(list); pv = (struct Value*)DLinkList_Current(list); printf("%d ", pv->v); printf("Length: %d ", DLinkList_Length(list)); DLinkList_Destroy(list); system("pause"); return 0; }