循环链表介绍
循环链表是另一种形式的链表,它提供了更为灵活的遍历表元素的能力。循环链表可以是单向的或双向的,但区分一个链表是不是循环链表只要看它有没有尾部元素即可。在循环链表中,最后一个元素的next指针又指回头元素而不是设置为NULL。在双向循环链表中,头元素的prev指针则指向最后一个元素,这使得循环链表中的每个元素既可以看做头元素也可以看做尾元素。遍历循环链表可以从任何一个元素位置开始。
单向循环链表的实现
// CList.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <malloc.h> /*循环链表元素结构体定义*/ typedef struct CListElmt_ { unsigned int uiValueA; /*数据域 数据成员*/ unsigned int *puiValueB; /*数据域 数据成员,需要动态申请内存*/ struct CListElmt_ *pNext; /*指针域 指向后一个元素结点的指针*/ }CListElmt; /*循环链表结构体定义*/ typedef struct CList_ { int iSize; /*链表大小*/ void (*destory)(void *data); /*用于释放元素结点内动态申请的内存*/ int (*compare)(void *key1, void *key2); /*比较函数 返回值 0 相等 1 大于 -1 小于*/ CListElmt *pCListElmtHead; /*指向链表头结点的指针*/ /*循环链表无尾结点指针*/ }CList; /*循环链表操作宏定义*/ #define CLIST_SIZE(clist) ((clist)->iSize) #define CLIST_HEAD(clist) ((clist)->pCListElmtHead) /*函数声明*/ void MemoryFree(void *data); int DataCompare(void *key1, void *key2); void CList_Init(CList *clist, void (*destory)(void *data), int (*compare)(void *key1, void *key2)); int CList_Insert_Next(CList *clist, CListElmt *Lelement, unsigned int uiDataA, unsigned int *puiDataB); int CList_Remove_Next(CList *clist, CListElmt *Lelement, unsigned int *puiDataA, unsigned int **puiDataB); void CList_Destory(CList *clist); /* *函数名:MemoryFree *参数:data 待释放的内存 *功能:释放动态申请的内存 *返回值:无 *作者:AlbertoNo1 *日期:2016-04-20 */ void MemoryFree(void *data) { free(data); } /* *函数名:DataCompare *参数:key1 待比较的元素1 * key2 待比较的元素2 *功能:比较两个元素的大小(无符号整型) *返回值:0 key1 等于 key2 1 key1 大于 key2 -1 key1 小于 key2 *作者:AlbertoNo1 *日期:2016-04-20 */ int DataCompare(void *key1, void *key2) { unsigned int uiKey1 = 0; unsigned int uiKey2 = 0; uiKey1 = *((unsigned int*)key1); uiKey2 = *((unsigned int*)key2); if (uiKey1 < uiKey2) { return -1; } else if (uiKey1 > uiKey2) { return 1; } else { return 0; } } /* *函数名:CList_Init *参数:clist 待初始化的链表 * destory 数据域动态内存释放函数 * compare 比较函数 *功能:循环链表初始化函数 *返回值:无 *作者:AlbertoNo1 *日期:2016-04-27 */ void CList_Init(CList *clist, void (*destory)(void *data), int (*compare)(void *key1, void *key2)) { clist->iSize = 0; clist->destory = destory; clist->compare = compare; clist->pCListElmtHead = NULL; } /* *函数名:CList_Insert_Next *参数:clist 链表 * Lelment 待插入元素的前一个元素指针 * uiDataA 数据成员值 * puiDataB 数据成员值(动态申请内存) *功能:循环链表插入元素函数 *返回值:0 成功 -1 失败 *作者:AlbertoNo1 *日期:2016-04-27 */ int CList_Insert_Next(CList *clist, CListElmt *Lelement, unsigned int uiDataA, unsigned int *puiDataB) { CListElmt *pElment = NULL; /*入参合法值由调用者保证*/ /*申请内存*/ pElment = (CListElmt*)malloc(sizeof(CListElmt)); if (NULL == pElment) { return -1; } /*数据域赋值*/ pElment->uiValueA = uiDataA; pElment->puiValueB = puiDataB; if (0 == CLIST_SIZE(clist)) {/*空链表插入元素*/ pElment->pNext = pElment; /*更新链表头结点指针*/ clist->pCListElmtHead = pElment; } else { pElment->pNext = Lelement->pNext; Lelement->pNext = pElment; } clist->iSize++; return 0; } /* *函数名:CList_Remove_Next *参数:clist 链表 * Lelment 待删除元素的前一个元素指针 * puiDataA 返回数据成员值 * puiDataB 返回数据成员值(动态申请内存) *功能:循环链表删除元素函数 *返回值:0 成功 -1 失败 *作者:AlbertoNo1 *日期:2016-04-27 */ int CList_Remove_Next(CList *clist, CListElmt *Lelement, unsigned int *puiDataA, unsigned int **puiDataB) { CListElmt *pElment = NULL; /*入参合法值由调用者保证*/ if (0 == CLIST_SIZE(clist)) {/*空链表删除元素*/ return -1; } pElment = Lelement->pNext; /*数据域返回*/ *puiDataA = pElment->uiValueA; *puiDataB = pElment->puiValueB; if (Lelement->pNext == Lelement) {/*删除最后一个元素*/ clist->pCListElmtHead = NULL; } else { Lelement->pNext = Lelement->pNext->pNext; if (pElment == CLIST_HEAD(clist)) { clist->pCListElmtHead = pElment->pNext; } } /*释放链表结点内存*/ free(pElment); clist->iSize--; return 0; } /* *函数名:CList_Destory *参数:clist 链表 *功能:循环链表销毁函数 *返回值:无 *作者:AlbertoNo1 *日期:2016-04-27 */ void CList_Destory(CList *clist) { unsigned int uiDataA = 0; unsigned int *puiDataB = NULL; while (CLIST_SIZE(clist) > 0) { if ((0 == CList_Remove_Next(clist, CLIST_HEAD(clist), &uiDataA, &puiDataB)) && (NULL != clist->destory)) { clist->destory(puiDataB); } } } /*空链表插入*/ void test_func1(CList *clist) { int iRet = 0; unsigned int uiDataA = 0; unsigned int *puiDataB = NULL; CListElmt *element = NULL; /*测试*/ uiDataA = 11; puiDataB = (unsigned int*)malloc(sizeof(unsigned int)); if (NULL == puiDataB) { return; } *puiDataB = 99; iRet = CList_Insert_Next(clist, NULL, uiDataA, puiDataB); if (-1 == iRet) { return; } printf("预期结果\n"); printf("数据:11 99 \n"); printf("链表大小:1 \n"); printf("\n实际结果\n"); printf("数据:"); for(element = CLIST_HEAD(clist); NULL != element; element = element->pNext) { printf("%u %u", element->uiValueA, *(element->puiValueB)); if (CLIST_HEAD(clist) == element->pNext) { break; } } printf("\n链表大小:%d \n", CLIST_SIZE(clist)); } /*非空链表插入*/ void test_func2(CList *clist) { int iRet = 0; unsigned int uiDataA = 0; unsigned int *puiDataB = NULL; CListElmt *element = NULL; /*测试*/ uiDataA = 12; puiDataB = (unsigned int*)malloc(sizeof(unsigned int)); if (NULL == puiDataB) { return; } *puiDataB = 98; iRet = CList_Insert_Next(clist, CLIST_HEAD(clist), uiDataA, puiDataB); if (-1 == iRet) { return; } printf("预期结果\n"); printf("数据:11 99 12 98\n"); printf("链表大小:2 \n"); printf("\n实际结果\n"); printf("数据:"); for(element = CLIST_HEAD(clist); NULL != element; element = element->pNext) { printf("%u %u ", element->uiValueA, *(element->puiValueB)); if (CLIST_HEAD(clist) == element->pNext) { break; } } printf("\n链表大小:%d \n", CLIST_SIZE(clist)); } /*非空链表插入*/ void test_func3(CList *clist) { int iRet = 0; unsigned int uiDataA = 0; unsigned int *puiDataB = NULL; CListElmt *element = NULL; /*测试*/ uiDataA = 13; puiDataB = (unsigned int*)malloc(sizeof(unsigned int)); if (NULL == puiDataB) { return; } *puiDataB = 97; iRet = CList_Insert_Next(clist, CLIST_HEAD(clist), uiDataA, puiDataB); if (-1 == iRet) { return; } printf("预期结果\n"); printf("数据:11 99 13 97 12 98\n"); printf("链表大小:3 \n"); printf("\n实际结果\n"); printf("数据:"); for(element = CLIST_HEAD(clist); NULL != element; element = element->pNext) { printf("%u %u ", element->uiValueA, *(element->puiValueB)); if (CLIST_HEAD(clist) == element->pNext) { break; } } printf("\n链表大小:%d \n", CLIST_SIZE(clist)); } int _tmain(int argc, _TCHAR* argv[]) { int iRet = 0; CList stCList = {0}; CListElmt *element = NULL; /*链表初始化*/ CList_Init(&stCList, MemoryFree, DataCompare); printf("\n\n"); test_func1(&stCList); printf("\n\n"); test_func2(&stCList); printf("\n\n"); test_func3(&stCList); /*链表销毁*/ CList_Destory(&stCList); printf("\n\n"); printf("iSize = %u Headaddr = %x", stCList.iSize, stCList.pCListElmtHead); getchar(); return 0; }
// CDList.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <malloc.h> /*双向循环链表元素结构体定义*/ typedef struct CDListElmt_ { unsigned int uiValueA; /*数据域 数据成员*/ unsigned int *puiValueB; /*数据域 数据成员,需要动态申请内存*/ struct CDListElmt_ *pNext; /*指针域 指向后一个元素结点的指针*/ struct CDListElmt_ *pPrev; /*指针域 指向前一个元素结点的指针*/ }CDListElmt; /*循环链表结构体定义*/ typedef struct CDList_ { int iSize; /*链表大小*/ void (*destory)(void *data); /*用于释放元素结点内动态申请的内存*/ int (*compare)(void *key1, void *key2); /*比较函数 返回值 0 相等 1 大于 -1 小于*/ CDListElmt *pCDListElmtHead; /*指向链表头结点的指针*/ /*循环链表无尾结点指针*/ }CDList; /*循环链表操作宏定义*/ #define CDLIST_SIZE(cdlist) ((cdlist)->iSize) #define CDLIST_HEAD(cdlist) ((cdlist)->pCDListElmtHead) /*函数声明*/ void MemoryFree(void *data); int DataCompare(void *key1, void *key2); void CDList_Init(CDList *cdlist, void (*destory)(void *data), int (*compare)(void *key1, void *key2)); int CDList_Insert_Next(CDList *cdlist, CDListElmt *Lelement, unsigned int uiDataA, unsigned int *puiDataB); int CDList_Insert_Prev(CDList *cdlist, CDListElmt *Lelement, unsigned int uiDataA, unsigned int *puiDataB); int CDList_Remove(CDList *cdlist, CDListElmt *Lelement, unsigned int *puiDataA, unsigned int **puiDataB); void CDList_Destory(CDList *cdlist); /* *函数名:MemoryFree *参数:data 待释放的内存 *功能:释放动态申请的内存 *返回值:无 *作者:AlbertoNo1 *日期:2016-04-20 */ void MemoryFree(void *data) { free(data); } /* *函数名:DataCompare *参数:key1 待比较的元素1 * key2 待比较的元素2 *功能:比较两个元素的大小(无符号整型) *返回值:0 key1 等于 key2 1 key1 大于 key2 -1 key1 小于 key2 *作者:AlbertoNo1 *日期:2016-04-20 */ int DataCompare(void *key1, void *key2) { unsigned int uiKey1 = 0; unsigned int uiKey2 = 0; uiKey1 = *((unsigned int*)key1); uiKey2 = *((unsigned int*)key2); if (uiKey1 < uiKey2) { return -1; } else if (uiKey1 > uiKey2) { return 1; } else { return 0; } } /* *函数名:CDList_Init *参数:cdlist 待初始化的链表 * destory 数据域动态内存释放函数 * compare 比较函数 *功能:双向循环链表初始化函数 *返回值:无 *作者:AlbertoNo1 *日期:2016-04-27 */ void CDList_Init(CDList *cdlist, void (*destory)(void *data), int (*compare)(void *key1, void *key2)) { cdlist->iSize = 0; cdlist->destory = destory; cdlist->compare = compare; cdlist->pCDListElmtHead = NULL; } /* *函数名:CDList_Insert_Next *参数:cdlist 链表 * Lelment 待插入元素的前一个元素指针 * uiDataA 数据成员值 * puiDataB 数据成员值(动态申请内存) *功能:双向循环链表插入元素函数(指定元素之后) *返回值:0 成功 -1 失败 *作者:AlbertoNo1 *日期:2016-04-27 */ int CDList_Insert_Next(CDList *cdlist, CDListElmt *Lelement, unsigned int uiDataA, unsigned int *puiDataB) { CDListElmt *pElment = NULL; /*入参合法值由调用者保证*/ /*申请内存*/ pElment = (CDListElmt*)malloc(sizeof(CDListElmt)); if (NULL == pElment) { return -1; } /*数据域赋值*/ pElment->uiValueA = uiDataA; pElment->puiValueB = puiDataB; if (0 == CDLIST_SIZE(cdlist)) {/*空链表插入元素*/ pElment->pNext = pElment; pElment->pPrev = pElment; /*更新链表头结点指针*/ cdlist->pCDListElmtHead = pElment; } else { pElment->pNext = Lelement->pNext; pElment->pPrev = Lelement; Lelement->pNext->pPrev = pElment; Lelement->pNext = pElment; } cdlist->iSize++; return 0; } /* *函数名:CDList_Insert_Prev *参数:cdlist 链表 * Lelment 待插入元素的前一个元素指针 * uiDataA 数据成员值 * puiDataB 数据成员值(动态申请内存) *功能:双向循环链表插入元素函数(指定元素之前) *返回值:0 成功 -1 失败 *作者:AlbertoNo1 *日期:2016-04-27 */ int CDList_Insert_Prev(CDList *cdlist, CDListElmt *Lelement, unsigned int uiDataA, unsigned int *puiDataB) { CDListElmt *pElment = NULL; /*入参合法值由调用者保证*/ /*申请内存*/ pElment = (CDListElmt*)malloc(sizeof(CDListElmt)); if (NULL == pElment) { return -1; } /*数据域赋值*/ pElment->uiValueA = uiDataA; pElment->puiValueB = puiDataB; if (0 == CDLIST_SIZE(cdlist)) {/*空链表插入元素*/ pElment->pNext = pElment; pElment->pPrev = pElment; /*更新链表头结点指针*/ cdlist->pCDListElmtHead = pElment; } else { pElment->pNext = Lelement; pElment->pPrev = Lelement->pPrev; Lelement->pPrev->pNext = pElment; Lelement->pPrev = pElment; } cdlist->iSize++; return 0; } /* *函数名:CDList_Remove *参数:cdlist 链表 * Lelment 待删除元素指针 * puiDataA 返回数据成员值 * puiDataB 返回数据成员值(动态申请内存) *功能:双向循环链表删除元素函数 *返回值:0 成功 -1 失败 *作者:AlbertoNo1 *日期:2016-04-27 */ int CDList_Remove(CDList *cdlist, CDListElmt *Lelement, unsigned int *puiDataA, unsigned int **puiDataB) { CDListElmt *pElment = NULL; /*入参合法值由调用者保证*/ if (0 == CDLIST_SIZE(cdlist)) {/*空链表删除元素*/ return -1; } pElment = Lelement; /*数据域返回*/ *puiDataA = pElment->uiValueA; *puiDataB = pElment->puiValueB; if (Lelement->pNext == Lelement) {/*删除最后一个元素*/ cdlist->pCDListElmtHead = NULL; } else { Lelement->pPrev->pNext = Lelement->pNext; Lelement->pNext->pPrev = Lelement->pPrev; if (pElment == CDLIST_HEAD(cdlist)) { cdlist->pCDListElmtHead = pElment->pNext; } } /*释放链表结点内存*/ free(pElment); cdlist->iSize--; return 0; } /* *函数名:CDList_Destory *参数:cdlist 链表 *功能:双向循环链表销毁函数 *返回值:无 *作者:AlbertoNo1 *日期:2016-04-27 */ void CDList_Destory(CDList *cdlist) { unsigned int uiDataA = 0; unsigned int *puiDataB = NULL; while (CDLIST_SIZE(cdlist) > 0) { if ((0 == CDList_Remove(cdlist, CDLIST_HEAD(cdlist), &uiDataA, &puiDataB)) && (NULL != cdlist->destory)) { cdlist->destory(puiDataB); } } } /*空链表插入*/ void test_func1(CDList *cdlist) { int iRet = 0; unsigned int uiDataA = 0; unsigned int *puiDataB = NULL; CDListElmt *element = NULL; /*测试*/ uiDataA = 11; puiDataB = (unsigned int*)malloc(sizeof(unsigned int)); if (NULL == puiDataB) { return; } *puiDataB = 99; iRet = CDList_Insert_Next(cdlist, NULL, uiDataA, puiDataB); if (-1 == iRet) { return; } printf("预期结果\n"); printf("数据:11 99 \n"); printf("链表大小:1 \n"); printf("\n实际结果1(顺序)\n"); printf("数据:"); for(element = CDLIST_HEAD(cdlist); NULL != element; element = element->pNext) { printf("%u %u ", element->uiValueA, *(element->puiValueB)); if (CDLIST_HEAD(cdlist) == element->pNext) { break; } } printf("\n链表大小:%d \n", CDLIST_SIZE(cdlist)); printf("\n实际结果2(逆序)\n"); printf("数据:"); for(element = CDLIST_HEAD(cdlist); NULL != element; element = element->pPrev) { printf("%u %u ", element->uiValueA, *(element->puiValueB)); if (CDLIST_HEAD(cdlist) == element->pPrev) { break; } } printf("\n链表大小:%d \n", CDLIST_SIZE(cdlist)); } /*非空链表插入*/ void test_func2(CDList *cdlist) { int iRet = 0; unsigned int uiDataA = 0; unsigned int *puiDataB = NULL; CDListElmt *element = NULL; /*测试*/ uiDataA = 12; puiDataB = (unsigned int*)malloc(sizeof(unsigned int)); if (NULL == puiDataB) { return; } *puiDataB = 98; iRet = CDList_Insert_Next(cdlist, CDLIST_HEAD(cdlist), uiDataA, puiDataB); if (-1 == iRet) { return; } printf("预期结果\n"); printf("数据:11 99 12 98\n"); printf("链表大小:2 \n"); printf("\n实际结果1(顺序)\n"); printf("数据:"); for(element = CDLIST_HEAD(cdlist); NULL != element; element = element->pNext) { printf("%u %u ", element->uiValueA, *(element->puiValueB)); if (CDLIST_HEAD(cdlist) == element->pNext) { break; } } printf("\n链表大小:%d \n", CDLIST_SIZE(cdlist)); printf("\n实际结果2(逆序)\n"); printf("数据:"); for(element = CDLIST_HEAD(cdlist); NULL != element; element = element->pPrev) { printf("%u %u ", element->uiValueA, *(element->puiValueB)); if (CDLIST_HEAD(cdlist) == element->pPrev) { break; } } printf("\n链表大小:%d \n", CDLIST_SIZE(cdlist)); } /*非空链表插入*/ void test_func3(CDList *cdlist) { int iRet = 0; unsigned int uiDataA = 0; unsigned int *puiDataB = NULL; CDListElmt *element = NULL; /*测试*/ uiDataA = 13; puiDataB = (unsigned int*)malloc(sizeof(unsigned int)); if (NULL == puiDataB) { return; } *puiDataB = 97; iRet = CDList_Insert_Next(cdlist, CDLIST_HEAD(cdlist), uiDataA, puiDataB); if (-1 == iRet) { return; } printf("预期结果\n"); printf("数据:11 99 13 97 12 98\n"); printf("链表大小:3 \n"); printf("\n实际结果1(顺序)\n"); printf("数据:"); for(element = CDLIST_HEAD(cdlist); NULL != element; element = element->pNext) { printf("%u %u ", element->uiValueA, *(element->puiValueB)); if (CDLIST_HEAD(cdlist) == element->pNext) { break; } } printf("\n链表大小:%d \n", CDLIST_SIZE(cdlist)); printf("\n实际结果2(逆序)\n"); printf("数据:"); for(element = CDLIST_HEAD(cdlist); NULL != element; element = element->pPrev) { printf("%u %u ", element->uiValueA, *(element->puiValueB)); if (CDLIST_HEAD(cdlist) == element->pPrev) { break; } } printf("\n链表大小:%d \n", CDLIST_SIZE(cdlist)); } /*非空链表插入*/ void test_func4(CDList *cdlist) { int iRet = 0; unsigned int uiDataA = 0; unsigned int *puiDataB = NULL; CDListElmt *element = NULL; /*测试*/ uiDataA = 14; puiDataB = (unsigned int*)malloc(sizeof(unsigned int)); if (NULL == puiDataB) { return; } *puiDataB = 96; iRet = CDList_Insert_Prev(cdlist, CDLIST_HEAD(cdlist), uiDataA, puiDataB); if (-1 == iRet) { return; } printf("预期结果\n"); printf("数据:11 99 13 97 12 98 14 96 \n"); printf("链表大小:4 \n"); printf("\n实际结果1(顺序)\n"); printf("数据:"); for(element = CDLIST_HEAD(cdlist); NULL != element; element = element->pNext) { printf("%u %u ", element->uiValueA, *(element->puiValueB)); if (CDLIST_HEAD(cdlist) == element->pNext) { break; } } printf("\n链表大小:%d \n", CDLIST_SIZE(cdlist)); printf("\n实际结果2(逆序)\n"); printf("数据:"); for(element = CDLIST_HEAD(cdlist); NULL != element; element = element->pPrev) { printf("%u %u ", element->uiValueA, *(element->puiValueB)); if (CDLIST_HEAD(cdlist) == element->pPrev) { break; } } printf("\n链表大小:%d \n", CDLIST_SIZE(cdlist)); } int _tmain(int argc, _TCHAR* argv[]) { int iRet = 0; CDList stCDList = {0}; CDListElmt *element = NULL; /*链表初始化*/ CDList_Init(&stCDList, MemoryFree, DataCompare); printf("\n\n"); test_func1(&stCDList); printf("\n\n"); test_func2(&stCDList); printf("\n\n"); test_func3(&stCDList); printf("\n\n"); test_func4(&stCDList); /*链表销毁*/ CDList_Destory(&stCDList); printf("\n\n"); printf("iSize = %u Headaddr = %x", stCDList.iSize, stCDList.pCDListElmtHead); getchar(); return 0; }