分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 代码编程

NetBSD Make源代码阅读三:链表之插入、查找、删除与对每个节点应用函数

发布时间:2023-09-06 02:15责任编辑:白小东关键词:源代码

1. 插入节点

在指定节点后面插入新的节点。这个函数首先检查参数的有效性。然后分两种情况处理插入:

   1> 如果要插入的链表为空,新节点是链表的第一个节点,新初化新节点以后,直接让firstPtr与lastPtr指向这个节点。

   2>如果链表中已有其它节点,就改变前后节点的指针,将新节点插入。

/*- *----------------------------------------------------------------------- * Lst_InsertAfter -- * ???创建新节点并插入到所给链表的指定节点之后 * * 输入: * ???l ???????操作的链表 * ???ln ???????在此节点后插入 * ???d ???????数据 * * : * ???如果一切正常,返回SUCCESS ?* * 副作用: * ???创建了新的节点,并链入链表之中。如果ln是链表的最后一个节点链表的变 ??* ???量lastPtr将会改变。 ?* ???如果链表为空,且ln为NULL,lastPtr 与firstPtr都会改变。 ?* ????* *----------------------------------------------------------------------- */ReturnStatusLst_InsertAfter(Lst l, LstNode ln, void *d){ ???List ????list; ???ListNode ???lNode; ???ListNode ???nLNode; ??????/*下面两个if语句检查参数的有效性*/ ???if (LstValid (l) && (ln == NULL && LstIsEmpty (l))) { ???goto ok; ???} ???if (!LstValid (l) || LstIsEmpty (l) ?|| ! LstNodeValid (ln, l)) { ???return (FAILURE); ???} ???ok: /*参数有效*/ ???list = l; ???lNode = ln; ???/*分配新节点,并链入数据*/ ???PAlloc (nLNode, ListNode); ??????????????nLNode->datum = d; ???nLNode->useCount = nLNode->flags = 0; ???if (lNode == NULL) { ??/*链表为空*/ ???if (list->isCirc) { /*循环链表,节点前后指针指向自身*/ ???????nLNode->nextPtr = nLNode->prevPtr = nLNode; ????} else { ???????nLNode->nextPtr = nLNode->prevPtr = NULL;/*节点前后指针为NULL*/ ???} ???/*既是第一个节点,也是最后一个*/ ???list->firstPtr = list->lastPtr = nLNode; ?????} else { ???nLNode->prevPtr = lNode; ????????????nLNode->nextPtr = lNode->nextPtr; ???lNode->nextPtr = nLNode; ???if (nLNode->nextPtr != NULL) { ???????nLNode->nextPtr->prevPtr = nLNode; ???} ???if (lNode == list->lastPtr) { /*如果是在最后插入,改变lastPtr*/ ???????list->lastPtr = nLNode; ???} ???} ???return (SUCCESS);}

2. 查找节点

/*- *----------------------------------------------------------------------- * Lst_FindFrom -- * ???从指定节点开始查找与所给客户数据一致的节点,使用客户提供的比较函数 * ???来确定数据是否一致。 * ????* * 结果: * ???找到的节点或者NULL * * 副作用: * ???无 * *----------------------------------------------------------------------- */LstNodeLst_FindFrom(Lst l, LstNode ln, const void *d, ????????int (*cProc)(const void *, const void *)){ ???ListNode ???tln; ??????/*检查参数有效性*/ ???if (!LstValid (l) || LstIsEmpty (l) || !LstNodeValid (ln, l)) { ???return NULL; ???} ???tln = ln; ???/*遍历节点*/ ???do { ????????????????????if ((*cProc)(tln->datum, d) == 0) /*比较节点所含数据与所给的是否一样*/ ???????return (tln); ???tln = tln->nextPtr; ???} while (tln != ln && tln != NULL); ???return NULL;}

 

3. 删除节点

/*- *----------------------------------------------------------------------- * Lst_Remove -- * ???删除指定链表的指定节点 * * 返回值: * ???SUCCESS 或者 FAILURE. * * 副作用: * ???如果ln为最后一个节点,firstPtr将被设成NULL. ?* ???如果ln为第一个节点或者最后一个节点, * ???链表的firsPtr与lastPtreither 将相应地发生变化。 *----------------------------------------------------------------------- */ReturnStatusLst_Remove(Lst l, LstNode ln){ ???List ????list = l; ???ListNode ???lNode = ln; ???if (!LstValid (l) || ?????????????/*检查参数*/ ???!LstNodeValid (ln, l)) { ???????return (FAILURE); ???} ???/* ????* 从链表中断开链接 ????*/ ???if (lNode->nextPtr != NULL) { ???lNode->nextPtr->prevPtr = lNode->prevPtr; ???} ???if (lNode->prevPtr != NULL) { ???lNode->prevPtr->nextPtr = lNode->nextPtr; ???} ???/* ????* 如果 firstPtr或者lastPtr指向这个节点, ????* 则相应地调整它们。 ????*/ ???if (list->firstPtr == lNode) { ???list->firstPtr = lNode->nextPtr; ???} ???if (list->lastPtr == lNode) { ???list->lastPtr = lNode->prevPtr; ???} ???/* ????* 顺序访问相关代码.如果我们正在删除的是链表的当前节点 ?????* 重新设定当前节点为前一节点. 如果 ????* 前一节点不存在(prevPtr == NULL), 把链表的结尾设成 ????* Unknown. ????*/ ???if (list->isOpen && (list->curPtr == lNode)) { ???list->curPtr = list->prevPtr; ???if (list->curPtr == NULL) { ???????list->atEnd = Unknown; ???} ???} ???/* ????* firstPtr仍然指向ln的唯一一种情况就是它是列表剩下的 ?????* 最后一个节点。 (这是循环列表,所以lNode->nextptr == lNode) ????* ?因此,删除之后列表为空,要做如下的标记 ????*/ ???if (list->firstPtr == lNode) { ???list->firstPtr = NULL; ???} ???/* ????* 注意客户数据(the datum)没有删除。调用者必须 ????* 负责释放它。 ????*/ ???if (lNode->useCount == 0) { ???free(ln); ???} else { ???lNode->flags |= LN_DELETED; ???} ???return (SUCCESS);}

 4. 对节点应用函数

/*- *----------------------------------------------------------------------- * Lst_ForEachFrom -- * ???Apply the given function to each element of the given list. The * ???function should return 0 if traversal should continue and non- * ???zero if it should abort. * * Results: * ???None. * * Side Effects: * ???Only those created by the passed-in function. * *----------------------------------------------------------------------- *//*VARARGS2*/intLst_ForEachFrom(Lst l, LstNode ln, int (*proc)(void *, void *), ???????void *d){ ???ListNode ???tln = ln; ???List ????list = l; ???ListNode ???next; ???Boolean ????????????done; ???int ????????????????result; ???if (!LstValid (list) || LstIsEmpty (list)) { ???return 0; ???} ???do { ???/* ????* Take care of having the current element deleted out from under ????* us. ????*/ ???next = tln->nextPtr; ???/* ????* We‘re done with the traversal if ????* ?- the next node to examine is the first in the queue or ????* ???doesn‘t exist and ????* ?- nothing‘s been added after the current node (check this ????* ???after proc() has been called). ????*/ ???done = (next == NULL || next == list->firstPtr); ???(void) tln->useCount++; ???result = (*proc) (tln->datum, d); ???(void) tln->useCount--; ???/* ????* Now check whether a node has been added. ????* Note: this doesn‘t work if this node was deleted before ????* ??????the new node was added. ????*/ ???if (next != tln->nextPtr) { ???????next = tln->nextPtr; ???????done = 0; ???} ???if (tln->flags & LN_DELETED) { ???????free((char *)tln); ???} ???tln = next; ???} while (!result && !LstIsEmpty(list) && !done); ???return result;}

NetBSD Make源代码阅读三:链表之插入、查找、删除与对每个节点应用函数

原文地址:https://www.cnblogs.com/RbtreeLinux/p/3633237.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved