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

福州网站建设工作室企业推广是什么意思

福州网站建设工作室,企业推广是什么意思,湖南益阳网站建设,wordpress_独立网页一、双向链表基础 双向链表示意图(指针永远指向内存开始的区域) 二、双向链表核心操作 1. 创建双向链表 c /*** 创建双向链表头节点* return 成功返回链表指针,失败返回NULL*/ struct DouLinkList* CreateDouLinkList() {// 分配链表头结构…

一、双向链表基础

双向链表示意图(指针永远指向内存开始的区域)

二、双向链表核心操作

1. 创建双向链表

c

/*** 创建双向链表头节点* @return 成功返回链表指针,失败返回NULL*/
struct DouLinkList* CreateDouLinkList()
{// 分配链表头结构体内存struct DouLinkList* dl = (struct DouLinkList*)malloc(sizeof(struct DouLinkList));if(NULL == dl){fprintf(stderr, "CreateDouLinkList malloc error\n");return NULL;}// 初始化链表为空状态dl->head = NULL;  // 头指针置空dl->clen = 0;     // 长度计数器归零return dl;
}

2. 头插法插入节点

 图解第一种情况:

 图解第二种情况:

 

c

/*** 在链表头部插入新节点* @param dl 链表指针* @param data 要插入的数据指针* @return 成功返回0,失败返回1*/
int InsertHeadDouLinkList(struct DouLinkList* dl, struct DATATYPE* data)
{// 为新节点分配内存struct DouNode* newnode = (struct DouNode*)malloc(sizeof(struct DouNode));if(NULL == newnode){fprintf(stderr, "InsertHeadDouLinkList malloc failed\n");return 1;}// 拷贝数据到新节点memcpy(&newnode->data, data, sizeof(struct DATATYPE));// 初始化新节点指针newnode->next = NULL;newnode->prev = NULL;// 新节点指向原头节点newnode->next = dl->head;// 如果原链表非空,设置原头节点的前驱指针if(dl->head){dl->head->prev = newnode;}// 更新链表头指针dl->head = newnode;// 链表长度增加dl->clen++;return 0;
}

3. 双向遍历链表

c

/*** 遍历打印链表内容* @param dl 链表指针* @param dir 遍历方向(FORWADR正向/BACKWADR反向)* @return 总是返回0*/
int ShowDouLinkList(struct DouLinkList* dl, DIR dir)
{struct DouNode* tmp = dl->head;if(FORWADR == dir)  // 正向遍历{printf("Forward traversal:\n");while(tmp){// 打印节点数据printf("Name: %s, Sex: %c, Age: %d, Score: %d\n", tmp->data.name, tmp->data.sex, tmp->data.age, tmp->data.score);tmp = tmp->next;  // 移动到下一个节点}}else if(BACKWADR == dir)  // 反向遍历{printf("Backward traversal:\n");// 先移动到链表尾部while(tmp->next){tmp = tmp->next;}// 从尾部向前遍历while(tmp){printf("Name: %s, Sex: %c, Age: %d, Score: %d\n", tmp->data.name, tmp->data.sex, tmp->data.age, tmp->data.score);tmp = tmp->prev;  // 移动到前一个节点}}return 0;
}

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

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

4. 尾插法插入节点

c

/*** 在链表尾部插入新节点* @param dl 链表指针* @param data 要插入的数据指针* @return 成功返回0,失败返回1*/
int InserTailDouLinkList(struct DouLinkList* dl, struct DATATYPE* data)
{// 空链表直接调用头插法if(IsEmptyDouLinkList(dl)){return InsertHeadDouLinkList(dl, data);}// 查找尾节点struct DouNode* tmp = dl->head;while(tmp->next){tmp = tmp->next;}// 创建新节点struct DouNode* newnode = malloc(sizeof(struct DouNode));if(newnode == NULL){fprintf(stderr, "InserTailDouLinkList malloc failed\n");return 1;}// 初始化新节点memcpy(&newnode->data, data, sizeof(struct DATATYPE));newnode->next = NULL;       // 尾节点的next为NULLnewnode->prev = tmp;        // 前驱指向原尾节点// 将新节点链接到链表尾部tmp->next = newnode;// 链表长度增加dl->clen++;return 0;
}

5. 指定位置插入节点

 

c

/*** 在指定位置插入新节点* @param dl 链表指针* @param data 要插入的数据指针* @param pos 插入位置(0-based)* @return 成功返回0,失败返回1*/
int InserPosDouLinkList(struct DouLinkList* dl, struct DATATYPE* data, int pos)
{int len = GetSizeDouLinkList(dl);// 检查位置合法性if(pos < 0 || pos > len){fprintf(stderr, "Invalid position %d\n", pos);return 1;}// 处理头插和尾插特殊情况if(0 == pos){return InsertHeadDouLinkList(dl, data);}else if(pos == len){return InserTailDouLinkList(dl, data);}// 创建新节点struct DouNode* newnode = malloc(sizeof(struct DouNode));if(newnode == NULL){fprintf(stderr, "InserPosDouLinkList malloc failed\n");return 1;}// 初始化新节点数据memcpy(&newnode->data, data, sizeof(struct DATATYPE));newnode->next = NULL;newnode->prev = NULL;// 定位到插入位置的前一个节点struct DouNode* tmp = dl->head;for(int i = 0; i < pos - 1; ++i){tmp = tmp->next;}// 重新链接指针newnode->next = tmp->next;  // 新节点后继指向原位置节点newnode->prev = tmp;        // 新节点前驱指向前驱节点tmp->next->prev = newnode;  // 原位置节点的前驱指向新节点tmp->next = newnode;        // 前驱节点的后继指向新节点// 链表长度增加dl->clen++;return 0;
}

6. 查找节点

c

/*** 按姓名查找节点* @param dl 链表指针* @param name 要查找的姓名* @return 找到返回节点指针,未找到返回NULL*/
struct DouNode* FindDouLinkList(struct DouLinkList* dl, char *name)
{// 空链表直接返回NULLif(IsEmptyDouLinkList(dl)){return NULL;}struct DouNode* tmp = dl->head;// 遍历链表查找匹配节点while(tmp){if(strcmp(tmp->data.name, name) == 0){return tmp;  // 找到匹配节点}tmp = tmp->next;  // 继续检查下一个节点}return NULL;  // 遍历结束未找到
}

7. 修改节点数据

c

/*** 修改指定节点的数据* @param dl 链表指针* @param name 要修改的节点姓名* @param data 新数据指针* @return 成功返回0,失败返回1*/
int ModifyDouLinkList(struct DouLinkList* dl, char *name, struct DATATYPE* data)
{// 查找目标节点struct DouNode* ret = FindDouLinkList(dl, name);if(NULL == ret){fprintf(stderr, "Node %s not found\n", name);return 1;}// 拷贝新数据到目标节点memcpy(&ret->data, data, sizeof(struct DATATYPE));return 0;
}

8. 双向链表逆序

c

/*** 反转双向链表* @param dl 链表指针* @return 成功返回0,失败返回1*/
int RevertDouLinkList(struct DouLinkList* dl)
{int len = GetSizeDouLinkList(dl);// 长度小于2无需反转if(len < 2){return 1;}// 初始化三个工作指针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;
}

9. 删除指定节点

c

/*** 删除指定节点* @param dl 链表指针* @param name 要删除的节点姓名* @return 成功返回0,失败返回1*/
int DeleteDouLinkList(struct DouLinkList* dl, char* name)
{// 查找目标节点struct DouNode* tmp = FindDouLinkList(dl, name);if(NULL == tmp){fprintf(stderr, "Node %s not found\n", name);return 1;}// 处理头节点情况if(tmp == dl->head){dl->head = dl->head->next;if(dl->head){dl->head->prev = NULL;  // 新头节点的前驱置空}}// 处理尾节点情况else if(NULL == tmp->next){if(tmp->prev){tmp->prev->next = 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;
}

10. 销毁链表

c

/*** 销毁整个链表* @param dl 链表指针* @return 总是返回0*/
int DestroyDouLinkList(struct DouLinkList* dl)
{struct DouNode* tmp = dl->head;// 循环释放所有节点while(tmp){dl->head = dl->head->next;  // 头指针后移free(tmp);                  // 释放当前节点tmp = dl->head;             // 指向新的头节点}// 释放链表头结构free(dl);return 0;
}

三、Makefile工程管理

基础版本

makefile

# 简单Makefile示例
# 目标:依赖
a.out: main.c ./doulink.c# 编译命令(前面必须是tab)gcc main.c doulink.c# 清理目标
clean:rm a.out

推荐版本

makefile

# 定义编译器和编译选项
CC = gcc
CFLAGS = -Wall -g  # 开启所有警告和调试信息# 定义目标可执行文件
TARGET = app# 定义源文件
SRCS = main.c doulink.c# 默认目标规则
$(TARGET): $(SRCS)$(CC) $(CFLAGS) -o $@ $^# 清理规则
clean:rm $(TARGET).PHONY: clean  # 声明clean为伪目标

使用说明

  1. 编译:make (自动执行第一条规则)

  2. 运行:./app (或./a.out如果是基础版本)

  3. 清理:make clean (删除生成的可执行文件)

四、双向链表VS单向链表对比

特性单向链表双向链表
遍历方向仅能正向遍历可双向遍历
节点结构data + nextdata + prev + next
插入删除删除需遍历找前驱(O(n))直接操作前驱节点(O(1))
内存占用较小(少一个指针)较大(多一个指针)
适用场景简单线性数据,内存紧张需要频繁查找前驱或反向遍历

五、嵌入式开发建议

  1. 资源受限系统

    • 优先考虑单向链表节省内存

    • 静态分配节点内存池避免碎片

  2. 实时性要求高

    • 双向链表删除操作更高效

    • 可考虑使用循环双向链表

  3. 调试技巧

    bash

    gdb ./your_program
    (gdb) b DouLinkList.c:100  # 在指定行设断点
    (gdb) p *node              # 查看节点内容
    (gdb) bt                   # 查看调用栈
  4. 性能优化

    • 维护尾指针加速尾插操作

    • 使用内存池预分配节点

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

相关文章:

  • 内部优惠券网站建站搜索引擎营销分析
  • 高大上设计网站欣赏重庆百度seo排名
  • 做网站都需要用到什么网站外包一般多少钱啊
  • 承德 网站建设 网络推广 网页设计谷歌搜索引擎首页
  • 安徽省建设干部学校网站关停官网百度
  • 张家港建设局官方网站浏览器下载安装2022最新版
  • 网站开发建设总结营销型网站建设专家
  • 汽车网站建设的基本功能百度电脑版下载官方
  • 手机网站要求外链代发免费
  • 自己做考试题目网站seo关键词快速提升软件官网
  • 茂名企业自助建站教育培训机构平台
  • 做it行业招标网站关键词seo培训
  • 网站开发晋升空间 路径cba排名
  • 深圳常平网站建设制作公司万网注册域名查询
  • 黑白风格网站微信小程序开发流程
  • 企业局域网站建设如何在百度上做产品推广
  • 中铁建设集团登录系统seo的最终是为了达到
  • 做网站给不给源代码简述网站建设的一般流程
  • 常平镇网站建设网络推广外包流程
  • 电子 东莞网站建设网络营销软件
  • 怎么看网站是什么程序做的yahoo搜索引擎提交入口
  • 2008iis搭建网站山东一级造价师
  • 做静态网站的步骤零售客户电商网站
  • 学校招聘教师网站建设中国互联网协会
  • 兰州哪里做网站百度收录技巧
  • 国外域名的网站怎么做百度快速优化推广
  • 什么是营销型手机网站建设账户竞价托管公司
  • 郑州网络营销公司排名宁波seo公司
  • avada wordpress 演示重庆seo公司怎么样
  • 网站运营策划提案seo优化快速排名