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

1. 插入节点

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

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

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

/*-
 *-----------------------------------------------------------------------
 * Lst_InsertAfter --
 *    创建新节点并插入到所给链表的指定节点之后
 *
 * 输入:
 *    l        操作的链表
 *    ln        在此节点后插入
 *    d        数据
 *
 * :
 *    如果一切正常,返回SUCCESS
 *
 * 副作用:
 *    创建了新的节点,并链入链表之中。如果ln是链表的最后一个节点链表的变
 *    量lastPtr将会改变。
 *    如果链表为空,且ln为NULL,lastPtr 与firstPtr都会改变。
 *
 *
 *-----------------------------------------------------------------------
 */
ReturnStatus
Lst_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
 *
 * 副作用:
 *    无
 *
 *-----------------------------------------------------------------------
 */
LstNode
Lst_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 将相应地发生变化。
 *-----------------------------------------------------------------------
 */
ReturnStatus
Lst_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*/
int
Lst_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;
}

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

时间: 2024-11-10 05:30:21

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

数据结构Java实现03----单向链表的插入和删除

数据结构Java实现03----单向链表的插入和删除 文本主要内容: 链表结构 单链表代码实现 单链表的效率分析 一.链表结构:            概念: 链式存储结构是基于指针实现的.我们把一个数据元素和一个指针称为结点.   数据域:存数数据元素信息的域. 指针域:存储直接后继位置的域. 链式存储结构是用指针把相互直接关联的结点(即直接前驱结点或直接后继结点)链接起来.链式存储结构的线性表称为链表. 链表类型: 根据链表的构造方式的不同可以分为: 单向链表 单向循环链表 双向循环链表 二

手写BST插入查找删除

binary search\sort\find tree operations status InsertNode(Node* root, data x, Node* father) { if(root==NULL) { if(father==NULL) Tree empty; else { if(x<father->data) { father->left=new Node//inital left right NULL father->left->data=x; retu

单链表实现“插入”和“删除”操作

在单链表中,又如何实现"插入"和"删除"操作呢? 插入操作: 假设我们要在线性表的两个数据元素a和b之间插入一个数据元素x,已知p为其单链表存储结构中指向结点a的指针.为插入数据元素x,首先要生成一个数据域为x的结点,然后插入在单链表中.根据插入操作的逻辑定义,还需修改结点a中的指针域,令其指向结点x,而结点x中的指针域应该指向b结点,从而实现3个元素a,b和x之间逻辑关系的变化. 假设s为指向结点x的指针.则上述指针修改用语句描述即为: s->next=p-

简直offer之链表的插入和删除

在插入和删除链表的时候一定要注意不要让链表断了,另外要特别注意对头结点的单独考虑 参考剑指offer上第50页删除给定值的结点的代码.得知,要删除一个节点必须知道该节点的前一个节点.书上的代码使用pNode.next 和pNode.next.value来判断的 下面把代码附上,有个问题 public static ListNode deleteNode(ListNode head,int value){ if(head==null){ return null; } ListNode toBeDe

链表的插入、删除

结构体: 1 typedef struct Student{ 2 int m_val; 3 struct Student* m_next; 4 }NODE,*pNODE; 链表的插入: 1 //尾部插入 2 void linkInitTail(pNODE* pphead) 3 { 4 int val; 5 pNODE pNew,pTail; 6 while(scanf("%d",&val) == 1) 7 { 8 pNew = (pNODE)calloc(1,sizeof(NO

面试之路(10)-BAT面试之java实现单链表的插入和删除

链表的结构: 链表在空间是不连续的,包括: 数据域(用于存储数据) 指针域(用于存储下一个node的指针) 单项链表的代码实现: 节点类 构造函数 数据域的get,set方法 指针域的get,set方法 代码: public class Node { Object element; //数据域 Node next; //指针域 //构造方法 public Node(Object obj, Node nextval) { this.element = obj; this.next = nextva

单链表的插入和删除

1 #define OKO 1 2 #define ERROR 0 3 typedef struct Lnode{ 4 ElemType data;//数据域 5 struct Lnode *next; //指针域 6 }Lnode,*Linklist; 7 Lnode *LocateElem_L(Linklist L,Elemtype e){ 8 //在链表中查找值为e的数据元素 9 Lnode *p; 10 p=L->next; 11 while(p&&p->data!=e

二叉搜索树建立、插入、删除、前继节点、后继节点之c++实现

一.前言 一直以来,都对树有关的东西望而却步.以前每次说要看一看,都因为惰性,时间就那么荒废掉了.今天下个决心,决定好好的数据结构中的东西看一下.不知道看这篇文章的你,是不是和我有同样的感受,空有一颗努力的心,却迟迟没有付出行动.如果是的话,如果也想好好的把树的知识巩固一下的话,就让我们一起好好儿地把知识点过一遍吧.本文争取让看完的每一个没有基础的同学,都能有所收获.在正文开始前,先给自己加个油.加油(^ω^) 二.二叉搜索树的定义 二叉搜索树是指,对于某一个节点而言,它左边的节点都小于或等于它

Partition List(链表的插入和删除操作,找前驱节点)

Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x. You should preserve the original relative order of the nodes in each of the two partitions. For example,Given 1->4->3->2