前言:作为经常要使用的数据结构,单链和双链,c语言不像c++一样可以使用多态的特性,但我们又希望能够设计一组api,不仅实现单链和双链的基本操作,还要可以用于任何数据结构,打个粗糙的比喻,好比一条晾东西的铁链一样,每个环都有一个钩子,任何东西,只要能勾上那个钩子,就可以晾在铁链上,这里需要用到"C语言基础(一)"这一篇里面提到的一个小技巧,通过结构体成员,计算offset。从而获得结构体的地址,从而可以访问结构体里面的任何成员,ok,这里我们就把链表的node作为结构体的一个成员,就可以实现了
一、单向链表-api
//1)结构定义
typedef struct sll_node
{
sll_node *pNext;
}SLL_NODE;
typedef struct sll_link
{
SLL_NODE *pHead;
SLL_NODE *pTail;
int iSize;
}SL_LIST;
typedef void (*LINK_FUNC)(SLL_NODE *pNode);
//2)api实现
int slListInit(SL_LIST *pList)
{
pList->pHead = NULL;
pList->pTail = NULL;
pList->iSize = 0;
return 0;
}
SL_LIST *slListCreate(void)
{
SL_LIST *pList = ( SL_LIST *) malloc ((unsigned) sizeof (SL_LIST));
slListInit(pList);
return (pList);
}
int slListDelete(SL_LIST *pList)
{
free ((char *) pList);
return 0;
}
void slListPutAtHead(SL_LIST *pList, SLL_NODE *pNode)
{
if(pList->pHead != NULL)
{
pNode->pNext = pList->pHead;
}
else
{
pList->pTail = pNode;
}
pList->pHead = pNode;
pList->iSize++;
return;
}
void slListPutAtTail(SL_LIST *pList, SLL_NODE *pNode)
{
if(pList->pTail != NULL)
{
pList->pTail->pNext = pNode;
}
else
{
pList->pHead = pNode;
}
pList->pTail = pNode;
pList->iSize++;
return;
}
SLL_NODE *slListGet(SL_LIST *pList)
{
SLL_NODE *pNode = pList->pHead;
if(pNode == NULL)
{
return NULL;
}
if(pNode->pNext != NULL)
{
pList->pHead = pNode->pNext;
}
else
{
pList->pHead = NULL;
pList->pTail = NULL;
}
pList->iSize--;
return pNode;
}
//调用者需要保证删除的节点是属于该链表的
int slListRemove(SL_LIST *pList, SLL_NODE *pDeleteNode, SLL_NODE *pPrevNode)
{
if((pDeleteNode== NULL)||(pList->pHead == NULL))
{
return -1;
}
if((pPrevNode != NULL)&&(pPrevNode->pNext != pDeleteNode))
{
return -1;
}
if(pPrevNode == NULL)
{
pList->pHead = pDeleteNode->pNext;
if(pList->pHead == NULL)
{
pList->pTail = NULL;
}
}
else
{
pPrevNode->pNext = pDeleteNode->pNext;
if(pPrevNode->pNext == NULL)
{
pList->pTail = pPrevNode;
}
}
pList->iSize--;
return 0;
}
int slListCount(SL_LIST *pList)
{
return pList->iSize;
}
void slListTraverse(SL_LIST *plist, LINK_FUNC Func)
{
SLL_NODE *pNode = plist->pHead;
while(pNode!=NULL)
{
Func(pNode);
pNode = pNode->pNext;
}
return;
}
二、单向链表-扩展功能
//3)扩展-链表反转(原链表基础上实现反转)
SL_LIST *slListReverse(SL_LIST *pList)
{
if(pList == NULL)
{
return NULL;
}
SLL_NODE *pHead = pList->pHead;
if((pHead == NULL) || (pHead->pNext == NULL))
{
return pList;
}
pList->pTail = pList->pHead;
SLL_NODE *pCur = pHead;
SLL_NODE *pSavePrev = NULL;
SLL_NODE *pSaveNext = pCur->pNext;
while(pSaveNext != NULL)
{
pCur->pNext = pSavePrev;
pSavePrev = pCur;
pCur = pSaveNext;
pSaveNext = pSaveNext->pNext;
}
pCur->pNext = pSavePrev;
pList->pHead = pCur;
return pList;
}
//3)扩展-链表反转(创建新链表实现反转)
SL_LIST *slListReverse2(SL_LIST *pList)
{
if(pList->pHead == NULL)
{
return NULL;
}
SLL_NODE *pNode = slListGet(pList);
pNode->pNext = NULL;
SL_LIST *pTmpLinklist = slListCreate();
while(pNode != NULL)
{
pNode->pNext = NULL;
slListPutAtHead( pTmpLinklist , pNode);
pNode = slListGet(pList);
}
pList->pHead = pTmpLinklist->pHead;
pList->iSize = pTmpLinklist->iSize;
pTmpLinklist->pHead = NULL;
pTmpLinklist->iSize = 0;
slListDelete(pTmpLinklist);
return pList;
}
//3)扩展-判断链表中是否有环
bool IfCircleInLink(SL_LIST *pList )
{
if(pList->pHead == NULL)
{
return false;//没有环
}
SLL_NODE *pFast = head;
SLL_NODE *pSlow = head;
while((pFast->pNext != NULL) && (pFast-> pNext-> pNext != NULL))
{
pFast = pFast->pNext->pNext;
pSlow = pSlow->pNext;
if(pFast == pSlow)
{
return true;
}
}
return false;
}
三、单向链表-测试程序
#define OFFSET_OF(TYPE, MEM_NAME) ((unsigned long)&((TYPE *)0)->MEM_NAME)
#define MEM_TO_TYPE(pMem,TYPE, MEM_NAME) ((TYPE *)((unsigned long)(pMem)-OFFSET_OF(TYPE, MEM_NAME)))
typedef struct link_data
{
int iValue;
SLL_NODE node;
}LINK_DATA;
void printElem(SLL_NODE *pNode)
{
LINK_DATA *pData = MEM_TO_TYPE(pNode, LINK_DATA, node);
printf("iValue %d\n", pData->iValue);
return;
}
int _tmain(int argc, _TCHAR* argv[])
{
LINK_DATA data1;
data1.iValue = 1;
data1.node.pNext = NULL;
LINK_DATA data2;
data2.iValue = 2;
data2.node.pNext = NULL;
LINK_DATA data3;
data3.iValue = 3;
data3.node.pNext = NULL;
LINK_DATA data4;
data4.iValue = 4;
data4.node.pNext = NULL;
LINK_DATA data5;
data5.iValue = 5;
data5.node.pNext = NULL;
SL_LIST *pList = slListCreate();
slListPutAtHead(pList, &(data1.node));
slListPutAtHead(pList, &(data2.node));
slListPutAtHead(pList, &(data3.node));
slListPutAtHead(pList, &(data4.node));
slListPutAtHead(pList, &(data5.node));
printf("desc[create sllist] count[%d]\n", slListCount(pList));
slListTraverse(pList, printElem);
slListGet(pList);
printf("desc[after slListGet] count[%d]\n", slListCount(pList));
slListTraverse(pList, printElem);
pList = slListReverse(pList);
printf("desc[after reverse] count[%d]\n", slListCount(pList));
slListTraverse(pList, printElem);
pList = slListReverse2(pList);
printf("desc[after reverse2] count[%d]\n", slListCount(pList));
slListTraverse(pList, printElem);
int iRet = slListRemove(pList, &(data2.node), &(data3.node));
if(iRet != 0)
{
printf("desc[slListRemove] iRet[%d]\n", iRet);
}
printf("desc[after slListRemove] count[%d]\n", slListCount(pList));
slListTraverse(pList, printElem);
getchar();
return 0;
}
结果输出: