2.循环链表和双向链表

来源:互联网 发布:ubuntu vim设置 编辑:程序博客网 时间:2024/06/05 06:35

1.理论

在基础线性表结构上灵活扩展可以得到很多衍生的线性表,这些线性表主要是为了提高线性表的某一方面的性能而做了改进。这里单独要说一下较为常用的两种基础线性表扩展:循环链表和双向链表。
循环链表:基础链表的末尾指针一般指向NULL,循环链表的末尾指针指向头结点或第一个节点,这样在合并两个链表的时候打开一个缺口,首尾指针串接起来即可。
双向链表:其实现在一般用的链表多是双向链表,单向链表寻找前驱时必须遍历到指定节点,而双向链表直接访问即可,将最坏时间复杂度由O(n)降到了O(1)。

下面在基础线性链表的基础上修改得到双向链表的实现程序,部分演示代码如下,完整代码见附件(循环链表用的不太多,用到了的话直接在基础链表程序上修改一下就可以用了)
双向链表和单向链表代码实现的主要不同在于插入和删除时不仅要处理后节点指针还要处理前节点指针,一定要注意边界条件时的指针处理,否则写出的程序很容易出错。

2.双向链表程序

存储结构
typedef struct tagJWListNode{JWListElemelem;//数据元素struct tagJWListNode*pNext;//下一个节点指针struct tagJWListNode*pPrior;//上一个节点指针}JWListNode, *PJWListNode, JWList, *PJWList;
操作函数
/************************************************************************//* 从头部开始创建链表                                                           *//************************************************************************/JWList* JWListCreateFromHead(int nSize, JWListElem *pElemList){PJWList pHead, pRear, pNode;int i;//创建一个头结点if (NULL == (pRear = pHead = (PJWListNode)malloc(sizeof(JWListNode)))){return NULL;}pHead->elem   = (JWListElem)0;//这里假设类型为double,int和char均可用于存储长度pHead->pNext  = NULL;pHead->pPrior = NULL;if (0 == nSize){return pHead;}//nSize不为0,在尾结点后添加后续节点for (i = 0; i < nSize; i++){if (NULL == (pNode = (PJWListNode)malloc(sizeof(JWListNode)))){return pHead;}pHead->elem += 1;pNode->elem = pElemList[i];pNode->pPrior= pRear;pNode->pNext= pRear->pNext;pRear->pNext= pNode;pRear= pNode;}return pHead;}/************************************************************************//* 从尾部开始创建链表                                                           *//************************************************************************/JWList* JWListCreateFromTail(int nSize, JWListElem *pElemList){PJWList pHead, pNode;int i;//创建一个头结点if (NULL == (pHead = (PJWListNode)malloc(sizeof(JWListNode)))){return NULL;}pHead->elem= (JWListElem)0;//这里假设类型为double,int和char均可用于存储长度pHead->pNext= NULL;pHead->pPrior= NULL;if (0 == nSize){return pHead;}//nSize不为0,在头结点后添加后续节点for (i = 0; i < nSize; i++){if (NULL == (pNode = (PJWListNode)malloc(sizeof(JWListNode)))){return pHead;}pHead->elem += 1;pNode->elem = pElemList[i];pNode->pNext= pHead->pNext;pNode->pPrior= pHead;pHead->pNext= pNode;}return pHead;}/************************************************************************//*销毁整个链表                                                                  *//************************************************************************/void JWListDestroy( JWList *pList ){PJWListNode pNodePrev, pNode;pNode = pList;//删除包括头结点在内的所有节点while (pNode != NULL){pNodePrev = pNode;pNode = pNode->pNext;free(pNodePrev);}}/************************************************************************//* 获得指定索引的节点(0~长度-1)的值                                            *//************************************************************************/JWList_BOOL JWListGetAt( JWList *pList, const int nIndex, JWListElem *pElem ){int i;JWListNode *pNode;//检查索引合法性,包含表为空的情形if (nIndex < 0 || nIndex > (int)(pList->elem)-1){return JWLIST_FALSE;}//从头结点遍历到指定索引的节点pNode = pList;for (i = 0; i <= nIndex; i++){pNode = pNode->pNext;}//获取指定节点的值*pElem = pNode->elem;return JWLIST_TRUE;}/************************************************************************//* 在指定索引的节点(0~长度)前插入新节点,索引==长度时表示在末尾添加新节点      *//************************************************************************/JWList_BOOL JWListInsert( JWList *pList, const int nIndex, const JWListElem elem ){int i;JWListNode *pNodePrev, *pNode;//检查索引合法性,包含表为空的情形if (nIndex < 0 || nIndex > (int)(pList->elem)){return JWLIST_FALSE;}//从头结点遍历到指定索引的节点并记录其前驱节点pNode = pList;for (i = 0; i <= nIndex; i++){pNodePrev = pNode;pNode = pNode->pNext;}//添加指定节点if(NULL == (pNodePrev->pNext = (PJWListNode)malloc(sizeof(JWListNode)))){return JWLIST_FALSE;}pNodePrev->pNext->elem= elem;pNodePrev->pNext->pNext= pNode;pNodePrev->pNext->pPrior= pNodePrev;if (NULL != pNode)//不是在末尾插入{pNode->pPrior= pNodePrev->pNext;}pList->elem += 1;//长度+1return JWLIST_TRUE;}/************************************************************************//* 删除指定索引的节点(0~长度-1)                                           *//************************************************************************/JWList_BOOL JWListDelete( JWList *pList, const int nIndex, JWListElem *pElem ){int i;JWListNode *pNodePrev, *pNode;//检查索引合法性,包含表为空的情形if (nIndex < 0 || nIndex > (int)(pList->elem)-1){return JWLIST_FALSE;}//从头结点遍历到指定索引的节点并记录其前驱节点pNode = pList;for (i = 0; i <= nIndex; i++){pNodePrev = pNode;pNode = pNode->pNext;}//删除指定节点pNodePrev->pNext = pNode->pNext;if(NULL != pNode->pNext)//不是删除末尾节点{pNode->pNext->pPrior = pNodePrev;}pList->elem-= 1;//长度-1if (NULL != pElem){*pElem = pNode->elem;}free(pNode);return JWLIST_TRUE;}/************************************************************************//* 在线性表中遍历找到满足pCompare函数的索引返回索引指针,没找到则返回NULL     *//************************************************************************/PJWListNode JWListLocate( JWList *pList, const JWListElem elem, JWList_CompareFunc pCompare ){PJWListNode pNode;//跳过头结点pNode = pList->pNext;//遍历对比余下所有节点while (pNode != NULL){if (JWLIST_TRUE == pCompare(pNode->elem, elem))//找到满足要求的索引项{return pNode;}pNode = pNode->pNext;}return NULL;}/************************************************************************//* 获得线性表中指定节点的前一个节点    *//************************************************************************/PJWListNode JWListGetPrior(JWListNode *pNode){return pNode->pPrior;}

完整程序下载链接
原创,转载请注明来自http://blog.csdn.net/wenzhou1219
0 0
原创粉丝点击