数据结构-单向链表

前言:作为经常要使用的数据结构,单链和双链,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;
}
结果输出:




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值