第十二章 利用结构和指针

这章就是链表。先单链表,后双向链表。

总结:

单链表是一种使用指针来存储值的数据结构。链表中的每一个节点包括一个字段,用于指向链表的下一个节点。

有一个独立的根指针指向链表的第1个节点。

单链表仅仅能从一个方向遍历。

怎样insert单链表:1、新节点的link字段必须设置为指向它的后面节点。

2、前一个节点的link字段必须指向这个新节点。

为了防止可能会插入链表的起始位置这样的情况,在C中,能够保存一个指向必须进行改动的link字段的指针。而不是保存一个指向前一个节点的指针。





双链表中的每一个节点包括两个link字段:当中一个指向链表的下一个node。还有一个指向前一个node。

双链表有两个根指针,一个指向第一个node,还有一个指向最后一个node。因此遍历的过程中能够从不论什么一端開始。并且在遍历过程中够能够改变方向。

为了把一个新节点插入到双链表中。我们必须改动4个指针。新节点的前向和后向link字段必需被设置,前一个节点的fwd和后一个节点的bwd也要改动,指向新节点。





警告:

1、落到链表尾部的后面。

2、使用指针时应该格外小心。由于C并没有对他们的使用提供安全网。

3、从if语句中提炼语句可能会改变測试结果。





编程提示:

1、消除特殊情况使代码更易于维护。

2、不要轻易的进行提炼语句,这样会使你的语句更难维护。

编程实例:(本章就不再弄习题了,关于数据结构这块会有大量代码进行训练)

1、提炼后的单链表插入操作

  1. #include "stdlib.h"
  2.  
  3. typedef struct NODE
  4. {
  5. struct NODE *link;
  6. int value;
  7. } Node;
  8. int sll_int(register Node **linkp, int new_value)
  9. {
  10. register Node *current; //指向当前节点
  11. register Node *new_node; //指向插入节点
  12.  
  13. /*
  14. ** 寻找正确插入位置,按顺序訪问链表,直到有个值大于或等于新值
  15. */
  16. while ((current = current->link) != NULL && current->value < new_value)
  17. {
  18. linkp = ¤t->link; //移动linkp指向下一个Node的link
  19. }
  20. /* 分配新的内存,并存到新节点去 */
  21. new_node = (NODE *) malloc (sizeof(NODE));
  22. if (new_node == NULL)
  23. {
  24. return 0;
  25. }
  26. new_node->value = new_value;
  27. /* 插入新节点 */
  28. new_node->link = current;
  29. *linkp = new_node;
  30. return 1;
  31. }

2、双链表插入操作

  1. #include "stdlib.h"
  2.  
  3. typedef struct NODE
  4. {
  5. struct NODE *fwd;
  6. struct NODE *bwd;
  7. int value;
  8. }Node;
  9.  
  10. int dll_insert(Node *rootp, int value)
  11. {
  12. /* 把一个值插入到一个双向链表中。rootp是一个指向根节点的指针
  13. value 是插入的新值
  14. 返回值:假设已经存在链表中。返回0
  15. 假设内存不足导致无法插入,返回-1,成功返回1;
  16. */
  17. Node *this_node;
  18. Node *next_node;
  19. Node *new_node;
  20.  
  21. for (this_node = rootp; next_node != NULL; this_node = next_node )
  22. {
  23. if (next_node->value == value)
  24. return 0;
  25. if (next_node->value < value)
  26. break;
  27. next_node = next_node->fwd;
  28. }
  29. /* 为新节点申请内存空间*/
  30. new_node = (Node *) malloc (sizeof(Node));
  31. if (new_node == NULL)
  32. return -1;
  33. new_node->value = value;
  34. /*
  35. 插入节点
  36. if 不在链表尾部 then 不在链表起始位置 or 位于链表起始位置
  37. else 在链表尾部 then 不在链表起始位置 or 位于链表起始位置(空链表)
  38. */
  39. if (next_node->fwd != NULL)
  40. {
  41. /*不在链表尾部*/
  42. if (this_node != rootp)
  43. {
  44. /* 不在链表的头部 */
  45. this_node->fwd = new_node;
  46. next_node->bwd = new_node;
  47. new_node->bwd = this_node;
  48. new_node->fwd = next_node;
  49. }
  50. else
  51. {
  52. /* 在链表的头部*/
  53. rootp->fwd = new_node;
  54. next_node->bwd = new_node;
  55. new_node->bwd = rootp;
  56. new_node->fwd = next_node;
  57. }
  58. }
  59. else
  60. {
  61. /*在链表尾部*/
  62. if (this_node->bwd != rootp)
  63. {
  64. /* 不在链表的头部 */
  65. new_node->fwd = NULL;
  66. new_node->bwd = this_node;
  67. this_node->fwd = new_node;
  68. rootp->bwd = new_node;
  69. }
  70. else
  71. {
  72. /* 在链表的头部*/
  73. new_node->fwd = NULL;
  74. new_node->bwd = NULL;
  75. rootp->bwd = new_node;
  76. rootp->fwd = new_node;
  77. }
  78. }
  79.  
  80. }

版权声明:本文博客原创文章,博客,未经同意,不得转载。

C和指针 (pointers on C)——第十二章:利用结构和指针的更多相关文章

  1. C和指针 第十二章 使用结构和指针 双链表和语句提炼

    双链表中每个节点包含指向当前和之后节点的指针,插入节点到双链表中需要考虑四种情况: 1.插入到链表头部 2.插入到链表尾部 3.插入到空链表中 4.插入到链表内部 #include <stdio ...

  2. C和指针 第十二章 使用结构和指针

    链表是一种常用的数据结构,每个节点通过链或者指针链接在一起,程序通过间接指针访问链表中的节点. typedef struct Node { //指向下一个节点的指针 struct Node *next ...

  3. 《Linux命令行与shell脚本编程大全》第十二章 使用结构化命令

    许多程序要就对shell脚本中的命令施加一些逻辑控制流程. 结构化命令允许你改变程序执行的顺序.不一定是依次进行的 12.1 使用if-then语句 如下格式: if command then     ...

  4. perl5 第十二章 Perl5中的引用/指针

    第十二章 Perl5中的引用/指针 by flamephoenix 一.引用简介二.使用引用三.使用反斜线(\)操作符四.引用和数组五.多维数组六.子程序的引用  子程序模板七.数组与子程序八.文件句 ...

  5. [CSAPP笔记][第十二章并发编程]

    第十二章 并发编程 如果逻辑控制流在时间上是重叠,那么它们就是并发的(concurrent).这种常见的现象称为并发(concurrency). 硬件异常处理程序,进程和Unix信号处理程序都是大家熟 ...

  6. C primer plus 第五版十二章习题

    看完C prime plus(第五版)第十二章,随带完成了后面的习题. 1.不使用全局变量,重写程序清单12.4的程序. 先贴出12.4的程序,方便对照: /* global.c --- 使用外部变量 ...

  7. 《OpenCL异构并行编程实战》补充笔记散点,第五至十二章

    ▶ 第五章,OpenCL 的并发与执行模型 ● 内存对象与上下文相关而不是与设备相关.设备在不同设备之间的移动如下,如果 kernel 在第二个设备上运行,那么在第一个设备上产生的任何数据结果在第二个 ...

  8. 第十二章 Python文件操作【转】

    12.1 open() open()函数作用是打开文件,返回一个文件对象. 用法格式:open(name[, mode[, buffering[,encoding]]]) -> file obj ...

  9. 【C++】《C++ Primer 》第十二章

    第十二章 动态内存 目前为止,所使用的对象都有着严格定义的生存期. 全局对象在程序启动时分配,在程序结束时销毁.局部自动对象在进入其定义所在的程序块时被创建,在离开块时销毁.局部static对象在第一 ...

随机推荐

  1. (十二)RabbitMQ消息队列-性能测试

    原文:(十二)RabbitMQ消息队列-性能测试 硬件配置 宿主机用的联想3850X6的服务器四颗E7-4850v3的处理器,DDR4内存,两块1.25TB的pcie固态.在宿主机上使用的事esxi5 ...

  2. [HTTP] Understand 2xx HTTP Status Code Responses

    The 2xx family of status codes are used in HTTP responses to indicate success. Beyond the generic 20 ...

  3. Android中的消息机制:Handler消息传递机制 分类: H1_ANDROID 2013-10-27 22:54 1755人阅读 评论(0) 收藏

    参考<疯狂android讲义>第2版3.5 P214 一.背景 出于性能优化考虑,Android的UI操作并不是线程安全的,这意味着如果有多个线程并发操作UI组件,可能导致线程安全问题.为 ...

  4. Objective-C中 ==、isEqual、isEqualToString判断字符串相等

    图片发自简书App 在判断一个字符串类型的变量是否与某字符时相等,你可能写下这样一行代码 if (activityType == @"0"){} //activityType是某一 ...

  5. 【45.65%】【codeforces 560B】Gerald is into Art

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  6. Java开发报表——Grid++Report 报表设计器

    为了让数据显示的更加形象生动,报表在项目中差点儿是很常见的,可是大致能够分为两类: 一,图形:以图形的形式显示数据,比如柱状图,折线图,饼形图等等,这里有许多关于这方面的工具,比如JFreeChart ...

  7. PEM_密钥对生成与读取方法

    PS:欢迎转载,但请注明出处,谢谢配合. 前言: PEM是OpenSSL和许多其他SSL工具的标准格式,OpenSSL 使用PEM 文件格式存储证书和密钥.这种格式被设计用来安全的包含在ascii甚至 ...

  8. oracle改动登录认证方式

    通过配置sqlnet.ora文件.我们能够改动oracle登录认证方式. SQLNET.AUTHENTICATION_SERVICES=(NTS);基于操作系统的认证 SQLNET.AUTHENTIC ...

  9. 【u206】最大赢家

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] Nic和Susan在玩一个有趣的游戏:在游戏开始前,他们先约定一个正整数n,同时令m=1.游戏过程中, ...

  10. Android加载图片导致内存溢出(Out of Memory异常)

    Android在加载大背景图或者大量图片时,经常导致内存溢出(Out of Memory  Error),本文根据我处理这些问题的经历及其它开发者的经验,整理解决方案如下(部分代码及文字出处无法考证) ...