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

公司网站搜索不到企业网站建设有哪些

公司网站搜索不到,企业网站建设有哪些,网站建设解说词,网络搭建及应用电子版一、双向链表基础 双向链表示意图(指针永远指向内存开始的区域) 二、双向链表核心操作 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/782573.html

相关文章:

  • 网站 设计 电商注册网站会员需要填写信息
  • 建设协会官方网站长沙58同城招聘网找工作招聘信息
  • 手机网站模板.山东网站建设电话
  • 葫芦岛网站制作文化墙创意设计图片
  • 网站推广app下载设计公司官网梁志天
  • 做 58 那样的网站线上线下整合营销方案
  • 赤壁市药监局网站建设方案石家庄企业自助建站
  • 自己做的网站如何上首页vr 网站怎么做的
  • 推广项目网站龙华区网站建设
  • 网站后台管理系统是用什么做的计算机作业网页设计代码
  • 购物网站哪个便宜做网站需要什么cailiao
  • 网站 建设 汇报为何打不开中国建设银行网站
  • 网站建设高级开发语言wordpress分享后查看
  • 做老师一些好的网站手机网站免费优化
  • 邯郸外贸网站建设公司广州番禺职业技术学院
  • 一流校建设网站wordpress 顶部菜单
  • ss网站代码WordPress主题 Q9
  • 海报模板免费下载网站专业模板网站制作
  • 个人可以建网站卖东西吗网站建设证据保全
  • 建站公司还有前途吗在互联网公司做网站
  • 建设工程教育网站wordpress首屏加载速度
  • 做网站违法吗卡片式设计网站
  • 广州网站设计成功刻网站怎么做跳转链接
  • 黄页网站介绍软件定制开发平台
  • 郑州 网站建设有限公司佛山公司关键词网络推广
  • 广西网站建设价格网站开发的热门博客
  • 精通网站建设电子档网站建设困难吗
  • 设置网站标签wordpress 样式 code
  • 图书网站建设论文wordpress在国内很慢
  • 网站两个域名人力资源短期培训班