一、链表的设计原理(一般建议使用堆空间存放链表)

  1. 设计链表的节点(数据域+指针域)

  2. 创建链表头结点(head)头结点相当于定义这一条链表的起点(钥匙)
    初始化链表头结点(数据域 + 指针域)

  3. 创建链表子节点(node)子节点插入到头结点后面(可以存储更多信息)
    初始化链表子结点(数据域 + 指针域)

  4. 插入节点(insert)将创建的节点放进链表里面,创立完整链表。
    尾插法,将新节点放置链表末尾
    头插法,将新节点放置头结点后一个
    排序插法,可以按冲从小到大,也可以从大到小

  5. 剔除节点(delete)
    将不需要节点删除,将链表不需要的节点从链表中拿出来,从此和链表无关。
    原理是:使用链表头结点,遍历整个链表,将各节点中的数据与待删除数据作用是比对,可找到剔除节点的位置。将该节点从链表中删除。

  6. 修改节点内的数据
    更改节点数据域中的内容

  7. 销毁链表
    如果链表是使用堆空间存储,销毁链表时需使用free函数将每个节点的堆空间释放

二、链表代码设计 (双向循环链表)

  1. 设计链表的节点(数据域+指针域)
typedef struct double_clink_list
{int data;                          //数据域struct double_clink_list * next;   //后继指针struct double_clink_list * prev;  //前驱指针}double_cll,*double_cll_p;                //重命名
  1. 创建链表头结点(head)
/**********************************************************************
**函数    :double_cll_p init_double_cll(void)
**函数说明 : 创建头结点
**形参说明 :无
**返回值  :  成功返回 新创建的头结点地址  失败返回 空地址
**********************************************************************/
double_cll_p init_double_cll(void)                       //创建头节点
{double_cll_p head = calloc(1,sizeof(double_cll)); //申请堆空间存放头结点if(head == NULL)                                  //判断申请是否成功{printf("init_double_cll error\n");        return NULL;                                 //失败直接返回}head->data = 0;                                        //初始化数据域head->next = head;                                  //初始化后继指针head->prev = head;                                 //初始化前驱指针return head;                                       //返回头结点地址
}
  1. 创建链表子节点(node)
/**********************************************************************
**函数    :double_cll_p create_node_double_cll(int data)
**函数说明 : 创建子节点
**形参说明 : data 为存放在 子节点数据域的数据
**返回值  :  成功返回 新创建的子结点地址  失败返回 空地址
**********************************************************************/
double_cll_p create_node_double_cll(int data)           //创建子节点
{double_cll_p node = calloc(1,sizeof(double_cll)); //申请堆空间存放子节点if(node == NULL)                                  //判断申请是否成功{printf("create_node_double_cll error\n");        return NULL;                                  //失败直接返回}node->data = data;                                 //初始化数据域node->next = node;                                  //初始化后继指针node->prev = node;                                 //初始化前驱指针return node;                                       //返回子结点地址
}
  1. 插入节点(insert)
/**********************************************************************
**函数    :int tail_insert_double_cll(double_cll_p node,double_cll_p head)
**函数说明 : 尾插法,将新节点放置链表末尾
**形参说明 : node 为待插入子节点的地址    head为链表头节点的地址
**返回值  :  成功返回 0失败返回 -1
**********************************************************************/
int tail_insert_double_cll(double_cll_p node,double_cll_p head)//尾插法,将新节点放置链表末尾
{if(head == NULL || node == NULL)           //判断头结点与子节点地址是否为空{printf("tail_insert_double_cll error\n");return -1;                             //失败直接返回-1}//以下部分理解不了的自己画个图 或者 看我下面的图node->prev = head->prev;                    //子节点前驱指针 指向 头结点前驱指针指向的子节点node->next = head;                            //子节点后继指针 指向 头结点head->prev = node;                          //头节点前驱指针 指向 子结点node->prev->next = node;                 //头结点前驱指针 指向 的子节点的后继指针 指向 新子结点return 0;                                 //成功返回0}

尾插图解

/**********************************************************************
**函数    :int head_insert_double_cll(double_cll_p node,double_cll_p head)
**函数说明 : 头插法,将新节点放置头结点后一个
**形参说明 : node 为待插入子节点的地址    head为链表头节点的地址
**返回值  :  成功返回 0失败返回 -1
**********************************************************************/
int head_insert_double_cll(double_cll_p node,double_cll_p head)//头插法,将新节点放置头结点后一个
{if(head == NULL|| node == NULL)                //判断头结点与子节点地址是否为空{printf("head_insert_double_cll error\n");return -1;                             //失败直接返回-1}//以下部分理解不了的自己画个图 node->next = head->next;         //子节点后继指针 指向 头结点后继指针指向的子节点head->next = node;                    //头节点后继驱 指针 指向子结点node->prev = head;                 //子节点前驱指针 指向 头结点node->next->prev = node;         //头结点后继指针 指向 的子节点的前驱指针 指向 新子结点return 0;                         //成功返回0//或者//将新节点插入到head->next的前面 //tail_insert_double_cll(node,head->next);
}
/**********************************************************************
**函数    :int sort_insert_double_cll(double_cll_p node,double_cll_p head)
**函数说明 : 排序插法,可以按从从小到大排序插入,也可以从大到小排序插入
**形参说明 : node 为待插入子节点的地址    head为链表头节点的地址
**返回值  :  成功返回 0失败返回 -1
**********************************************************************/
int sort_insert_double_cll(double_cll_p node,double_cll_p head)//排序插法,可以按冲从小到大,也可以从大到小
{if(head == NULL || node == NULL)               //判断头结点与子节点地址是否为空{printf("sort_insert_double_cll error\n");return -1;                                 //失败直接返回-1}double_cll_p  p = head;                     //定义一个指针变量存放头结点地址for(;p->next != head;p = p->next)          //遍历整个链表,如果指针p再次指向head地址,说明已经遍历完{if(p->next->data > node->data)           //从小到大排序 插入{node->next = p->next;p->next = node;node->next->prev = node;node->prev = p;return 0;                          //插入成功返回0}//     if(p->next->data < node->data)     //从大到小排序插入//     {//         node->next = p->next;//         p->next = node;//         node->next->prev = node;//         node->prev = p;//         return 0;                     //插入成功返回0//     }}//如果链表只有头结点,那么子节点直接插入即可        node->next = p->next;p->next = node;node->next->prev = node;node->prev = p;return 0;                  //插入成功返回0
}
  1. 剔除节点(delete)
/**********************************************************************
**函数    :int del_double_cll(double_cll_p p,double_cll_p head)
**函数说明 : 删除指定地址的节点
**形参说明 : p 为待剔除子节点的地址    head为链表头节点的地址
**返回值  :  成功返回 0失败返回 -1
**********************************************************************/
int del_double_cll(double_cll_p p,double_cll_p head)//删除指定地址的节点
{if(p == NULL || head == NULL)          //判断头结点与子节点地址是否为空{printf("del_double_cll error\n");return -1;                         //失败直接返回-1}p->next->prev = p->prev;               //将要删除的子节点断链p->prev->next = p->next;              //将要删除的子节点断链p->next = NULL;                         //将要删除的子节点后继指针 指向 空p->prev = NULL;                          //将要删除的子节点前驱指针 指向 空free(p);                             //释放子节点的堆空间return 0;                            //剔除成功返回0
}
  1. 查找对应数据节点并返回该节点地址
/**********************************************************************
**函数    :double_cll_p find_double_cll(int data,double_cll_p head)
**函数说明 : 查找对应数据节点并返回该节点地址
**形参说明 : data 为待查找数据    head为链表头节点的地址
**返回值  :  成功返回 待查找数据节点地址失败返回 空地址
**********************************************************************/
double_cll_p find_double_cll(int data,double_cll_p head)//查找对应数据节点并返回该节点地址
{if(head == NULL)                     //判断头结点地址是否为空{printf("find_double_cll error\n");return NULL;                  //失败直接返回空地址}double_cll_p p = head->next;        //定义一个指针变量 存放 头结点后继指针指向节点 的地址for(;p != head; p = p->next)      //遍历整个链表,如果指针p再次指向head地址,说明已经遍历完{if(p->data == data)             //遍历的过程中,如果子节点数据 等于 待查找数据,则返回该子节点地址return p;                  //返回子节点地址}return NULL;                      //找不到返回 空地址
}
  1. 销毁链表
/**********************************************************************
**函数    :int free_double_cll(double_cll_p head)
**函数说明 : 释放链表所有内存
**形参说明 : head为链表头节点的地址
**返回值  :  成功返回 0失败返回 -1
**********************************************************************/
int free_double_cll(double_cll_p head)//释放链表所有内存
{if(head == NULL)                 //判断头结点地址是否为空{printf("double_cll not exist\n");return -1;                     //失败直接返回-1}double_cll_p p = head;              //定义一个指针变量 存放 头结点 的地址for(;p->next != head;)             //遍历整个链表,如果指针p再次指向head地址,说明已经遍历完{p = p->next;                 //变量p指向下一个节点free(p->prev);                   //释放前一个节点的 堆空间(断链)} free(p);                          //释放头节点 堆空间return 0;                            //链表销毁成功返回 0
}

完整 C程序 和 头文件

//双向循环链
#include "double_cll.h"int main(int argc,char *argv[])
{double_cll_p head = init_double_cll();//创建头结点int data;//输入数据double_cll_p q = NULL;//存放需要删除节点的地址while(1){scanf("%d",&data);//从键盘读取一个数据if(data>0){ if(NULL==find_double_cll(data,head))//禁止输入重复的数据{double_cll_p node = create_node_double_cll(data);//创建子节点sort_insert_double_cll(node,head);//使用排序插入方式将子节点插入到链表   }else{printf("data repetition \n");}show_double_cll(head); //使用链表正顺序输出  }else if(data ==0)break; else{if((q=find_double_cll(-data,head))!=NULL)//查找是否存在需要删除的数据{del_double_cll(q,head);//删除指定节点地址的 整个节点}else{printf("data absence \n"); }show_double_cll(head);//使用链表正顺序输出  }}free_double_cll(head);//释放内存return 0;
}double_cll_p init_double_cll(void)//创建头节点
{double_cll_p head = calloc(1,sizeof(double_cll));if(head == NULL){printf("init_double_cll error\n");        return NULL;}head->data = 0;head->next = head;head->prev = head;return head;
}double_cll_p create_node_double_cll(int data)//创建子节点
{double_cll_p node = calloc(1,sizeof(double_cll));if(node == NULL){printf("create_node_double_cll error\n");        return NULL;}node->data = data;node->next = node;node->prev = node;return node;
}int tail_insert_double_cll(double_cll_p node,double_cll_p head)//尾插法,将新节点放置链表末尾
{if(head == NULL || node == NULL){printf("tail_insert_double_cll error\n");return -1;}node->prev = head->prev;node->next = head;head->prev = node;node->prev->next = node;return 0;
}int head_insert_double_cll(double_cll_p node,double_cll_p head)//头插法,将新节点放置头结点后一个
{if(head == NULL|| node == NULL){printf("head_insert_double_cll error\n");return -1;}node->next = head->next;head->next = node;node->prev = head;node->next->prev = node;return 0;//将新节点插入到head->next的前面//tail_insert_double_cll(node,head->next);
}int sort_insert_double_cll(double_cll_p node,double_cll_p head)//排序插法,可以按冲从小到大,也可以从大到小
{if(head == NULL || node == NULL){printf("sort_insert_double_cll error\n");return -1;}double_cll_p  p = head;for(;p->next != head;p = p->next){if(p->next->data > node->data)//从小到大排序插入{node->next = p->next;p->next = node;node->next->prev = node;node->prev = p;return 0;}//     if(p->next->data < node->data)//从大到小排序插入//     {//         node->next = p->next;//         p->next = node;//         node->next->prev = node;//         node->prev = p;//         return 0;//     }}node->next = p->next;p->next = node;node->next->prev = node;node->prev = p;return 0;
}int show_double_cll(double_cll_p head)//按链表正顺序输出
{if(head == NULL){printf("show_double_cll error\n");return -1;}double_cll_p p = head;for(;p->next!=head;p = p->next){printf("%d\t",p->next->data);}printf("\n");return 0;
}double_cll_p find_double_cll(int data,double_cll_p head)//查找对应数据节点并返回该节点地址
{if(head == NULL){printf("find_double_cll error\n");return NULL;}double_cll_p p = head->next;for(;p != head; p = p->next){if(p->data == data)   return p;//重复返回1}return NULL;//没有重复
}int free_double_cll(double_cll_p head)//释放链表所有内存
{if(head == NULL){printf("double_cll not exist\n");return -1;}double_cll_p p = head;for(;p->next != head;){p = p->next;free(p->prev);} free(p);return 0;
}int del_double_cll(double_cll_p p,double_cll_p head)//删除指定地址的节点
{if(p == NULL || head == NULL){printf("del_double_cll error\n");return -1;}p->next->prev = p->prev;p->prev->next = p->next;p->next = NULL;p->prev = NULL;free(p);return 0;
}
#ifndef __double_cll_h__
#define __double_cll_h__#include<stdio.h>
#include <stdlib.h> typedef struct double_clink_list
{int data;struct double_clink_list * next;struct double_clink_list * prev;}double_cll,*double_cll_p;double_cll_p init_double_cll(void);//创建头节点
double_cll_p create_node_double_cll(int data);//创建子节点int tail_insert_double_cll(double_cll_p node,double_cll_p head);//尾插法,将新节点放置链表末尾
int head_insert_double_cll(double_cll_p node,double_cll_p head);//头插法,将新节点放置头结点后一个
int sort_insert_double_cll(double_cll_p node,double_cll_p head);//排序插法,可以按冲从小到大,也可以从大到小int show_double_cll(double_cll_p head);//按链表正顺序输出
double_cll_p find_double_cll(int data,double_cll_p head);//查找对应数据节点并返回该节点地址
int free_double_cll(double_cll_p head);//释放链表所有内存
int del_double_cll(double_cll_p p,double_cll_p head);//删除指定地址的节点#endif

结束语:需要完整C程序的私信我发邮箱

【C语言】链表的一般设计步骤相关推荐

  1. c语言链表p-%3enext,课程设计报告.c语言程序设计.pdf

    课程设计报告.c语言程序设计 学生成绩管理 C语言课程设计报告 学 院 _信息学院_ 专 业 软件工程 班 级 _ _ 学 号 姓 名 课 题 _C语言课程设计_ 指导教师 __ 杨老师 _ 报告成绩 ...

  2. 基于web的c语言在线编译器的设计步骤,基于WEB的C语言在线学习系统毕业设计(全)..doc...

    PAGE 学科分类号 0806 本科生毕业设计 题目(中文):基于WEB的C语言在线学习系统的实现 (英文) The Implementation of an Online Learning Syst ...

  3. 基于web的c语言在线编译器的设计步骤,定稿毕业论文基于WEB的C语言在线学习系统毕业设计完整版(范文1)...

    <[毕业论文]基于WEB的C语言在线学习系统毕业设计.doc>由会员分享,可免费在线阅读全文,更多与<(定稿)毕业论文基于WEB的C语言在线学习系统毕业设计(完整版)>相关文档 ...

  4. 猴子吃桃问题c语言链表,数据结构课程设计--猴子吃桃子问题.doc

    Data organization curriculm project 数据结构课程设计 设计题目: 猴子吃桃子问题 专业班级: 通信工程0804班 学生学号: 0909082421 学生姓名: 王 ...

  5. 一步一步教你从零开始写C语言链表(超详细)

    STM32 HAL开发完全指南 写文章 一步一步教你从零开始写C语言链表(超详细) 杨源鑫 嵌入式系统工程师.物联网创业合伙人,业务经理兼产品经理 285 人赞同了该文章 为什么要学习链表? 链表主要 ...

  6. 使用C语言链表创建学生信息并且将信息打印输出

    C语言文章更新目录 C/C++学习资源(百度云盘链接) 计算机二级资料(过级专用) C语言学习路线(从入门到实战) 编写C语言程序的7个步骤和编程机制 C语言基础-第一个C程序 C语言基础-简单程序分 ...

  7. 第1节:C语言发展及基本格式步骤

    一  C语言发展 1:1970年美国贝尔实验室的Ken Thompson以BCPL(Basic Combined Programming Language)语言为基础,设计出了很简单且很接近硬件的B语 ...

  8. c语言程序设计 在线课程设计,c语言程序设计 本科课程设计

    <c语言程序设计 本科课程设计>由会员分享,可在线阅读,更多相关<c语言程序设计 本科课程设计(11页珍藏版)>请在人人文库网上搜索. 1.河北农业大学本 科 课 程 设 计课 ...

  9. c语言编译前端,c语言编译器前端的设计与实现.doc

    c语言编译器前端的设计与实现 计 算 机 与 信 息 工 程 学 院 软硬件专业综合课程设计总结报告 题目: C语言编译器前端的设计与实现 姓 名: 学 号: 专 业: 计算机科学与技术 指导教师: ...

最新文章

  1. 用-force –opengl 指令_苹果新系统ios14新功能汇总 轻点背面等小技巧怎么用
  2. hadoop balance failed
  3. PHPStorm无法保存个人设置 ctrl左键无法找到类
  4. java怎么将前端的数据存到关联的表中_Java程序员最可能被考到的14个面试题
  5. 发现还是 True Image Server v8.1.941 比较好用
  6. android intent bundle传递参数,Android 使用Intent和Bundle传递数据及如何传递enum
  7. mysql与python交互
  8. Python循环遍历(cycle)
  9. linux 查看系统信息命令
  10. Mac ndk编译for Android
  11. [Windows]win10时间同步错误的解决方法
  12. POJ 4047 Garden 线段树 区间更新
  13. IIS7的HTTP 500.19错误
  14. 用hudson配置持续集成CI服务器几个关键的配置
  15. 解决分类中样本分布不平衡问题
  16. linux dd销毁数据,dd命令详解(清除硬盘数据)
  17. 华硕主板VMware中安装Ubuntu16.04中的BIOS设置问题
  18. [ZT]组策略软件分发部署
  19. 阿里云Redis开发遇到的问题总结
  20. 一节课轻松通关 Spark

热门文章

  1. [算法Tutorial]Adversary Argument,对手论证
  2. 安卓android项目源码微信天天动听滴滴打车订票软件
  3. 女人让男人自卑的九个经典事实
  4. 为什么对带www和不带www的域名ping结果不一致
  5. 机器学习 - 预测心脏病
  6. C语言标准 —— C89(C90)、C99、C11、C17、C2X
  7. 03|容器技术基本原理之Namespace
  8. The kernel modle installed correctly , but no devices were recognized.
  9. Hubble Zhang的学习日记(第九周)
  10. 【golang源码分析】chan底层原理——附带读写用户队列的环形缓冲区