当前位置: 首页 > wzjs >正文

网站后台做数据库备份代码磁力天堂

网站后台做数据库备份代码,磁力天堂,北京企业网站建设飞沐,怎样做省钱购物网站目录 一、双向链表 二、双向链表的基本操作 1、创建双向链表 2、头插法插入节点 3、遍历打印链表 4、判断双链表是否为空 5、获取双链表长度 6、尾插法插入节点 7、指定位置插入节点 8、查找(按姓名查找双链表节点) 9、修改链表的指定节点 三…

目录

一、双向链表

二、双向链表的基本操作

1、创建双向链表

2、头插法插入节点

3、遍历打印链表

4、判断双链表是否为空

5、获取双链表长度

6、尾插法插入节点

7、指定位置插入节点

8、查找(按姓名查找双链表节点)

9、修改链表的指定节点

三、扩展:工程管理工具(makefile)

一、双向链表

双向链表示意图

指针永远指向内存开始的区域

二、双向链表的基本操作

1、创建双向链表

struct DouLinkList* CreateDouLinkList()

 // 定义函数,返回双向链表结构体指针,用于创建双向链表头节点
{
        struct DouLinkList* dl = (struct DouLinkList*) malloc(sizeof(struct         DouLinkList));  // 为双向链表头节点分配内存
        if(NULL == dl)  // 检查内存分配是否失败
        {
        fprintf(stderr,"CreateDouLinkList malloc\n");  // 向标准错误输出内存分配失败信息
        return NULL;  // 分配失败,返回空指针
        }
        dl->head = NULL;  // 初始化头节点的head指针为NULL,表示空链表
        dl->clen = 0;  // 初始化链表长度计数器为0
        return dl;  // 返回创建好的双向链表头节点指针
}

2、头插法插入节点

(1)图解:

第一种情况:第一个插入

第二种情况:

(2)算法实现:

int InsertHeadDouLinkList(struct DouLinkList* dl, struct DATATYPE* data)

 // 定义头部插入函数,参数为链表指针和数据指针,返回操作状态(0成功,非0失败)
{
        struct DouNode * newnode = (struct DouNode*)malloc(sizeof(struct  DouNode));  // 为新节点分配内存
        if(NULL == newnode)  // 检查新节点内存分配是否失败
        {
                fprintf(stderr,"inserthead malloc\n");  // 输出插入节点时内存分配失败的错误信息
                return 1;  // 分配失败,返回错误码1
        }
        memcpy(&newnode->data,data,sizeof(struct DATATYPE));  // 将数据拷贝到新节点的数据域
        newnode->next = NULL;  // 初始化新节点的后继指针为NULL
        newnode->prev = NULL;  // 初始化新节点的前驱指针为NULL
 
        newnode->next = dl->head;  // 新节点的后继指向原链表头节点
        if(dl->head)  // 若原链表非空(存在头节点)
        {
                dl->head->prev = newnode;  // 原头节点的前驱指向新节点
        }
        dl->head = newnode;  // 更新链表头节点为新节点
        dl->clen++;  // 链表长度加1
        return 0;  // 插入成功,返回0
}

3、遍历打印链表

int ShowDouLinkList(struct DouLinkList* dl,DIR dir)  

// 定义遍历函数,参数为链表指针和遍历方向枚举值,返回操作状态(0成功)
{
        struct DouNode* tmp = dl->head;  // 定义临时指针tmp,初始指向链表头节点
        if(FORWADR == dir)  // 若遍历方向为正向(假设FORWADR为正向枚举值)
        {
                while(tmp)  // 正向遍历,直到tmp指向NULL(链表末尾)
                {
                        // 输出节点数据(假设data包含姓名、性别、年龄、分数字段)
                        printf("%s %c %d %d\n",tmp->data.name,tmp->data.sex,tmp->data.age,tmp->data.score);
                        tmp = tmp->next;  // tmp后移至下一个节点
                }
        }
        else if(BACKWADR == dir)  // 若遍历方向为反向(假设BACKWADR为反向枚举值)
        {
                while(tmp->next)  // 先移动到链表尾节点(通过判断next是否为NULL)
                {
                        tmp = tmp->next;
                } // 循环结束后tmp指向尾节点
 
                while(tmp)  // 从尾节点开始反向遍历,直到tmp指向NULL(头节点的前驱)
                {
                        // 输出节点数据(与正向相同)
                        printf("%s %c %d %d\n",tmp->data.name,tmp->data.sex,tmp->data.age,tmp->data.score);
                        tmp = tmp->prev;  // tmp前移至上一个节点
                }
        }
        return 0;  // 遍历完成,返回0
}

4、判断双链表是否为空

int IsEmptyDouLinkList(struct DouLinkList* dl) 
{
    return 0 == dl->clen; // 若链表长度(clen)为0,返回1(真),否则返回0(假)
}

5、获取双链表长度

int GetSizeDouLinkList(struct DouLinkList* dl) 
{
    return dl->clen; // 直接返回链表长度(clen)
}

6、尾插法插入节点

(1)图解

第一种情况(与头插第一种情况类似)

第二种:

(2)算法实现

int InserTailDouLinkList(struct DouLinkList* dl, struct DATATYPE* data)
{
    if (IsEmptyDouLinkList(dl)) // 检查链表是否为空
        {
            return InsertHeadDouLinkList(dl, data); // 空链表时调用头插法插入
        }
    else
        {
            struct DouNode* tmp = dl->head; // 临时指针指向头节点
            while (tmp->next) // 遍历到链表最后一个节点(tmp->next为空时停止)
                {
                    tmp = tmp->next; // 后移指针
                }
            struct DouNode* newnode = malloc(sizeof(struct DouNode)); // 分配新节点内存
            if (newnode == NULL) // 内存分配失败
                {
                    fprintf(stderr, "InserTailDouLinkList malloc\n"); // 输出错误信息到标准错误
                    return 1; // 返回错误码1
                }
            // 初始化新节点
            memcpy(&newnode->data, data, sizeof(struct DATATYPE)); // 复制数据到新节点
            newnode->next = NULL; // 新节点的next指针指向NULL(尾节点特性)
            newnode->prev = NULL; // 初始化为NULL(后续会重新指向前驱节点)

            // 连接链表
            newnode->prev = tmp; // 新节点的前驱指向最后一个节点tmp
            tmp->next = newnode; // tmp的后继指向新节点

            dl->clen++; // 链表长度加1
        }
    return 0; // 插入成功,返回0
}

7、指定位置插入节点

(1)图解:

(2)算法实现:

int InserPosDouLinkList(struct DouLinkList* dl, struct DATATYPE* data, int pos)
{
    int len = GetSizeDouLinkList(dl); // 获取当前链表长度
    if (pos < 0 || pos > len) // 检查位置是否合法(0 ≤ pos ≤ len)
        {
            return 1; // 非法位置,返回错误码1
        }
    if (0 == pos) // 插入位置为头部(pos=0)
        {
            return InsertHeadDouLinkList(dl, data); // 调用头插法插入
        }
    else if (pos == len) // 插入位置为尾部(pos=链表长度)
        {
            return InserTailDouLinkList(dl, data); // 调用尾插法插入
        }
    else // 插入位置在中间(1 ≤ pos ≤ len-1)
        {
            struct DouNode* newnode = malloc(sizeof(struct DouNode)); // 分配新节点内存
            if (newnode == NULL) // 内存分配失败
                {
                    fprintf(stderr, "InserTailDouLinkList malloc\n"); // 输出错误信息
                    return 1; // 返回错误码1
                }
            // 初始化新节点
            memcpy(&newnode->data, data, sizeof(struct DATATYPE)); // 复制数据到新节点
            newnode->next = NULL; // 初始化为NULL(后续会重新指向后继节点)
            newnode->prev = NULL; // 初始化为NULL(后续会重新指向前驱节点)

            struct DouNode* tmp = dl->head; // 临时指针指向头节点
            int i;
            for (i = 0; i < pos - 1; ++i) // 遍历到插入位置的前一个节点(pos-1处)
                {
                    tmp = tmp->next; // 后移指针
                }
                // 双向链表指针重连
                newnode->next = tmp->next; // 新节点的后继指向tmp的原后继
                newnode->prev = tmp; // 新节点的前驱指向tmp
                tmp->next->prev = newnode; // tmp原后继的前驱指向新节点
                tmp->next = newnode; // tmp的后继指向新节点
        }
    return 0; // 插入成功,返回0
}

8、查找(按姓名查找双链表节点)

(1)算法实现:

struct DouNode* FindDouLinkList(struct DouLinkList* dl, char *name) 
{

     if(IsEmptyDouLinkList(dl))
    {
        return NULL;
    }
    struct DouNode* tmp = dl->head; // 定义临时指针tmp,指向链表头节点
    while (tmp) // 遍历链表,直到tmp为NULL(指向空节点时停止)
    {
        if (strcmp(tmp->data.name, name) == 0) // 比较当前节点data中的name字段与目标name
        {
            return tmp; // 若匹配成功,返回当前节点指针
        }
        tmp = tmp->next; // 移动指针到下一个节点
    }
    return NULL; // 遍历结束未找到匹配节点,返回NULL
}

(2)调用:

9、修改链表的指定节点

int ModifyDouLinkList(struct DouLinkList* dl, char *name, struct DATATYPE* data)
{
    // 调用FindDouLinkList函数,根据name在双链表dl中查找节点
    // 将找到的节点指针赋给ret,如果没找到返回NULL
    struct DouNode* ret = FindDouLinkList(dl, name); 
    if (NULL == ret) // 判断是否找到节点
    {
        return 1; // 没找到节点,返回1表示修改失败
    }
    // 使用memcpy函数将data所指向的数据内容,复制到找到节点(ret)的数据部分
    // 复制的长度为struct DATATYPE的大小
    memcpy(&ret->data, data, sizeof(struct DATATYPE)); 
    return 0; // 成功修改节点数据,返回0表示操作成功
}

10、逆序双向链表

int RevertDouLinkList(struct DouLinkList* dl) {
    // 获取链表长度
    int len = GetSizeDouLinkList(dl);
    // 长度小于2无需反转
    if (len < 2) {
        return 1;
    }
    // 定义前驱指针(初始NULL)
    struct DouNode* Prev = NULL;
    // 当前节点指针(从头节点开始)
    struct DouNode* Tmp = dl->head;
    // 下一节点指针(保存当前节点的后继)
    struct DouNode* Next = Tmp->next;
    // 循环反转指针
    while (1) {
        // 当前节点的前驱指向原后继
        Tmp->prev = Next;
        // 当前节点的后继指向原前驱
        Tmp->next = Prev;
        // 前驱指针后移到当前节点
        Prev = Tmp;
        // 当前节点后移到原后继
        Tmp = Next;
        // 若当前节点为空,结束循环
        if (NULL == Tmp) {
            break;
        }
        // 下一节点后移(提前保存原后继的后继)
        Next = Next->next;
    }
    // 头指针指向新的头节点(原尾节点)
    dl->head = Prev;
    // 返回成功标识
    return 0;
}

11、删除链表指定节点

int DeleteDouLinkList(struct DouLinkList* dl, char* name) {
    // 查找指定name的节点
    struct DouNode* tmp = FindDouLinkList(dl, name);
    // 若节点不存在,返回失败
    if (NULL == tmp) {
        return 1;
    }
    // 处理头节点情况
    if (tmp == dl->head) {  
        // 头指针后移
        dl->head = dl->head->next;
        // 若新头节点存在,更新其前驱为NULL
        if (dl->head) {
            dl->head->prev = NULL;
        }
    }
    // 处理尾节点情况(next为空)
    else if (NULL == tmp->next) {  
        // 若当前节点有前驱,断开前驱与当前节点的连接
        if (tmp->prev) {
            tmp->prev->next = NULL;
        }
        // 若无前驱(说明只剩当前节点),置头指针为NULL
        else {
            dl->head = NULL;
        }
    }
    // 处理中间节点情况
    else {
        // 若存在后继节点,更新其后继的前驱指针
        if (tmp->next) tmp->next->prev = tmp->prev;
        // 若存在前驱节点,更新其前驱的后继指针
        if (tmp->prev) tmp->prev->next = tmp->next;
    }
    // 释放目标节点内存
    free(tmp);
    // 链表长度减一
    dl->clen--;
    // 返回成功标识
    return 0;
}

12、销毁链表

int DestroyDouLinkList(struct DouLinkList* dl) {
    // 获取头节点指针
    struct DouNode* tmp = dl->head;
    // 循环释放所有节点
    while (tmp) {
        // 头指针后移到下一个节点
        dl->head = dl->head->next;
        // 释放当前节点内存
        free(tmp);
        // tmp指向新的头节点(继续循环释放)
        tmp = dl->head;
    }
    // 释放链表头结构自身内存
    free(dl);
    // 返回成功标识
    return 0;
}

调用:

三、扩展:工程管理工具(makefile)

1、当三个以上的.c编译时:

(1)vi Makefile(makefile也可,推荐用首字母大写),进入下面的页面进行编写(也可在资源管理器中打开:

出现羊头标志即可)

        版本一:

1、 a.out: main.c ./doulink.c   // 规则1 ,生成可执行文件,其中./a.out为目标,冒号后的为依赖(输入结束回车)

2、        gcc main.c doulink.c  //前面必须为Tab键空格

3、

4、clean:   //可删除目标文件

5、        rm  a.out

        版本二:(推荐使用)

        版本二示例:

(2)make   (编译命令,默认只走第一条规则)

(3)./app (运行,版本一运行命令为 ./a.out)

2、扩展命令:make clean  (删除中间产生的文件)。

http://www.dtcms.com/wzjs/93702.html

相关文章:

  • 做网站前端用什么语言百度安装免费下载
  • 超值的网站建设谷歌广告投放
  • 大连网站建设设计公司公司产品推广方案
  • 武汉光谷发生枪击案aso苹果关键词优化
  • 聊天网站开发重庆seo务
  • 外贸网站怎么做优化河南省最新通知
  • 网站公司深圳网站优化和网站推广
  • 400网站建设办公58同城安居客
  • 织梦网站模板安装百度搜索词排名
  • 天津制作公司网站竞价广告代运营
  • 环境保护建设网站bing搜索
  • 网站设计为什么要域名网络推广营销培训机构
  • 中山建网站哪家好百度seo关键词优化费用
  • 母版做双语网站网络推广员好做吗
  • 昆明建设招投标网站拉新推广渠道
  • 微信支付申请网站吗搜索app下载
  • 哪个网站做的ppt模板好太原推广团队
  • 网站付款链接怎么做搜狗seo培训
  • 中文互联网巨头衰亡史天津网站优化软件
  • 做网站需要代码吗充电宝seo关键词优化
  • 电子商务网站建设内涵百度精准搜索
  • 网站结构优化怎么做搜索引擎优化的五个方面
  • 网页设计英语怎么说陕西seo推广
  • 公司的网站建设会计培训
  • 做外贸有哪些免费的网站长沙seo推广公司
  • 深圳公安门户网站官网网络营销推广网站
  • 媒体村网站建设阿里指数官网
  • ui设计主要做什么seo报价单
  • 有网址的公司宁宁网seo
  • 深圳网站建设php企业网络推广网站