zoukankan      html  css  js  c++  java
  • C和C指针小记(十八)-使用结构和指针-双向链表

    1、双链表

    1.1 双向链表的声明

    在一个双链表中,每个节点都包含两个指针--指向前一个节点的指针和指向后一个节点的指针.
    

    声明

    typedef struct NODE {
        struct NODE *fwd;
        struct NODE *bwd;
        int                value;
    } Node;
    

    根节点的fwd字段指向链表的第1个节点,根节点的bwd字段指向链表的最后一个节点.如果链表为空,这两个字段都为NULL.链表的第1个节点的bwd 字段和最后一个节点的 fwd 字段都为 NULL. 在一个有序的链表中,各个节点将根据value 字段的值以升序排列.

    3.2 双向链表的插入

    将一个新值插入到有序表中
    函数原型
    dll_insert( Node *rootp, int value );
    dll_insert 接受两个参数,一个指向根节点的指针和一个整型值.
    插入节点时,可能会遇到4中情况:
    1、新值可能必须插入到链表的中间位置
    2、新值可能必须插入到链表的起始位置
    3、新值可能必须插入到链表的结束位置
    4、新值可能必须既插入到链表的起始位置,又插入到链表的结束位置

    
    /**
     向双向链表中插入数据
    
     @param rootp 根节点
     @param value 带插入值
     @return 0 已经有值, -1 不能插入, 1 插入成功
     */
    int dll_insert( Dnode *rootp, int value) {
        Dnode   *this;
        Dnode   *next;
        Dnode   *newnode;
        
        //查看 value 是否已经存在于链表中, 如果是就返回.否则,为新值创建一个新节点(“newnode”将指向它)
        //this 将指向应该在新节点之前的那个节点
        //next 将指向应该在新节点之后的那个节点
        for( this = rootp; (next = this->fwd) != NULL; this = next){
            if (next->value == value) {
                return 0;
            }
            if (next->value > value) {
                break;
            }
        }
        
        newnode = (Dnode *)malloc( sizeof( Dnode) );
        if ( newnode == NULL) {
            return -1;
        }
        newnode->value = value;
        
        //把新值添加到链表中
        if ( next != NULL) {
            //情况 1,2 并非位于链表尾部.
            if ( this != rootp ) {//情况1 并非位于链表起始位置
                newnode->fwd = next;
                this->fwd = newnode;
                newnode->bwd = this;
                next->bwd = newnode;
            }else {// 情况2 位于起始位置
                newnode->fwd = next;
                this->fwd = newnode;
                newnode->bwd = NULL;
                next->bwd = newnode;
            }
        }else {
            //情况3,4 位于链表的尾部
            if (this != rootp) {// 情况3 并非位于链表的起始位置
                newnode->fwd = NULL;
                this->fwd = newnode;
                newnode->bwd = this;
                rootp->bwd = newnode;
            }else {// 情况4 位于链表起始位置
                newnode->fwd = NULL;
                this->fwd = newnode;
                newnode->bwd = NULL;
                rootp->bwd = newnode;
            }
        }
        
        return 1;
    }
    
    
    //添加节点的4种情况可以提炼
    if ( next != NULL) {
            //情况1 或 2 并非位于链表的尾部
            newnode->fwd = next;
            if (this != rootp ) {//情况1 并非位于链表的起始位置
                this->fwd = newnode;
                newnode->bwd = this;
            }else {//情况2 位于链表的起始位置
                rootp->fwd = newnode;
                newnode->bwd = NULL;
            }
            next->bwd = newnode;
        }else {
            //情况3或4 位于链表尾部
            newnode->fwd = NULL;
            if (this != rootp) {//情况3 并不位于链表起始位置
                this->fwd = newnode;
                newnode->bwd = this;
            }else {//情况4 位于链表起始位置
                rootp->fwd = newnode;
                newnode->bwd = NULL;
            }
            rootp->bwd = newnode;
        }
    
    
  • 相关阅读:
    Linux驱动入门(三)Led驱动
    Linux驱动入门(二)操作硬件
    mysql表的完整性约束
    数据库操作
    初识数据库
    mysql的安装、启动和基础配置 —— windows版本
    Socket网络编程
    python进阶之多线程(简单介绍协程)
    python进阶多进程(进程池,进程间通信)
    python基础之异常处理
  • 原文地址:https://www.cnblogs.com/wjw-blog/p/10457650.html
Copyright © 2011-2022 走看看