数据结构学习(二)——单链表的操作之头插法和尾插法创建链表

http://blog.csdn.net/abclixu123/article/details/8210109

链表也是线性表的一种,与顺序表不同的是,它在内存中不是连续存放的。在C语言中,链表是通过指针相关实现的。而单链表是链表的其中一种,关于单链表就是其节点中有数据域和只有一个指向下个节点的指针域。创建单链表的方法有两种,分别是头插法和尾插法。

所谓头插法,就是按节点的逆序方法逐渐将结点插入到链表的头部。反之尾插法就是按节点的顺序逐渐将节点插入到链表的尾部。相对来说,头插法要比尾插法算法简单,但是最后产生的链表是逆序的,即第一个输入的节点实际是链表的最后一个节点。而为了习惯,通常用尾插法来创建链表。下面的代码就是实现了头插法和尾插法。代码在Linux下调试通过。

[cpp] view plaincopy
print?
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3.   
  4. typedef struct link  
  5. {  
  6.     char data;  
  7.     struct link *next;  
  8. }linklist;  
  9.   
  10. linklist *CreateList_Front();   //头插法创建单链表  
  11. linklist *CreateList_End();     //尾插法创建单链表  
  12. void ShowLinklist(linklist *h); //输出显示链表  
  13.   
  14. int main(void)  
  15. {  
  16.     int choice;  
  17.     linklist *head;  
  18.   
  19.     //head = (linklist*)malloc(sizeof(linklist));  
  20.     while(1)  
  21.     {  
  22.         printf("单链表的创建\n");  
  23.         printf("1.使用头插法创建单链表\n");  
  24.         printf("2.使用尾插法创建单链表\n");  
  25.         printf("3.链表输出显示\n");  
  26.         printf("4.退出\n");  
  27.         printf("做出选择:\n");  
  28.         scanf("%d",&choice);  
  29.         switch(choice)  
  30.         {  
  31.         //头插法  
  32.         case 1:  
  33.             head = CreateList_Front();  
  34.             break;  
  35.         //尾插法  
  36.         case 2:  
  37.             head = CreateList_End();  
  38.             break;  
  39.         //输出链表  
  40.         case 3:  
  41.             ShowLinklist(head);  
  42.             break;  
  43.         //退出程序  
  44.         case 4:  
  45.             return 0;  
  46.             break;  
  47.         default:  
  48.             break;  
  49.         }  
  50.     }  
  51.     return 1;  
  52. }  
  53.   
  54. linklist *CreateList_Front()  
  55. {  
  56.     linklist *head, *p;  
  57.     char ch;  
  58.   
  59.     head = NULL;  
  60.     printf("依次输入字符数据(‘#’表示输入结束):\n");  
  61.     ch = getchar();  
  62.     while(ch != '#')  
  63.     {  
  64.         p = (linklist*)malloc(sizeof(linklist));  
  65.         p->data = ch;  
  66.         p->next = head;  
  67.         head = p;  
  68.         ch = getchar();             //头插法算法简单 核心就两句p->next = head;head = p;  
  69.     }  
  70.     return head;  
  71. }  
  72.   
  73. linklist *CreateList_End()  
  74. {  
  75.     linklist *head, *p, *e;  
  76.     char ch;  
  77.   
  78.     head = NULL;  
  79.     e = NULL;  
  80.     printf("请依次输入字符数据('#'表示输入结束):\n");  
  81.     ch = getchar();  
  82.     while(ch != '#')  
  83.     {  
  84.         p = (linklist*)malloc(sizeof(linklist));  
  85.         p->data = ch;  
  86.         if(head == NULL)        //先判断输入的是不是第一个节点  
  87.         {  
  88.             head = p;             
  89.         }  
  90.         else  
  91.         {  
  92.             e->next = p;     //e始终指向输入的最后一个节点  
  93.         }  
  94.         e = p;  
  95.         ch = getchar();           
  96.     }  
  97.     if(e != NULL)               //如果链表不为空,则最后节点的下一个节点为空  
  98.     {  
  99.         e->next = NULL;  
  100.     }  
  101.     return head;                //尾插法比头插法复杂一些,程序中要做两次判断,分别是判断第一个节点和最后一个节点的判断。且消耗多一个指针变量e。  
  102. }  
  103.   
  104. void ShowLinklist(linklist *h)  
  105. {  
  106.     linklist *p;  
  107.   
  108.     p = h;  
  109.     while(p != NULL)  
  110.     {  
  111.         printf("%c ", p->data);  
  112.         p = p->next;  
  113.     }  
  114.     printf("\n");  
  115. }  

通过上述代码可以看出,尾插法确实比头插法复杂点,多了两个判断。但是这是可以解决的,通过添加一个头节点,此节点不存放数据域,只是存放指向下个节点的指针域就是了。这样就可以免除掉两次判断。整体也要清晰点了。下面是增加一个头节点后尾插法的实现代码:

[cpp] view plaincopy
print?
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3.   
  4. typedef struct list  
  5. {  
  6.     char data;  
  7.     struct list *next;  
  8. }linklist;  
  9.   
  10. linklist *CreateList_End();     //尾插法创建链表  
  11. void ShowLinklist(linklist *h); //输出显示链表  
  12.   
  13. int main(void)  
  14. {  
  15.     linklist *head;  
  16.   
  17.     printf("使用尾插法创建链表(改进版)\n");  
  18.     printf("请依次输入字符数据(‘#’表示输入结束):\n");  
  19.     head = CreateList_End();        //创建链表  
  20.     ShowLinklist(head);             //输出链表  
  21. }  
  22.   
  23. linklist *CreateList_End()  
  24. {  
  25.     linklist *head, *p, *e;  
  26.     char ch;  
  27.   
  28.     head = (linklist*)malloc(sizeof(linklist));  
  29.     e = head;           //让e指向头节点  
  30.     ch = getchar();  
  31.     while(ch != '#')  
  32.     {  
  33.         p = (linklist*)malloc(sizeof(linklist));  
  34.         p->data = ch;   
  35.         e->next = p;     //把新节点添加到表尾  
  36.         e = p;              //把指针指向新节点  
  37.         ch = getchar();  
  38.     }     
  39.     e->next = NULL;          //尾节点的指针域置空  
  40.     return head;  
  41. }  
  42.   
  43. void ShowLinklist(linklist *h)  
  44. {  
  45.     linklist *p;  
  46.   
  47.     p = h->next;  
  48.     while(p != NULL)  
  49.     {  
  50.         printf("%c ", p->data);  
  51.         p = p->next;  
  52.     }  
  53.     printf("\n");  
  54. }  

添加了一个头节点后代码是不是就要清晰点了呢?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384074.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

信号的基本概念以及信号的产生

一. 信号产生的场景 1. 用户输入命令, 在shell 启动一个前台进程      2. 当用户按一下 Ctrl C 的时候,从键盘产生一个硬件中断      3. 此时CPU 正在执行这个进程的带代码, 则该进程的执行代码暂停执行, CPU 从用户态切换到内核态处理该硬件中断.      4. 中断…

HDU - 1028——母函数入门

【题目描述】 “Well, it seems the first problem is too easy. I will let you know how foolish you are later.” feng5166 says. “The second problem is, given an positive integer N, we define an equation like this: Na[1]a[2]a[3]…a[m]; a[i]>0,1<m<N;…

信号的阻塞

一. 阻塞信号 1.信号的相关概念     (1) 递达: 实际执行信号的处理动作称为信号的递达     (2) 未决: 信号从产生到递达之间的过程叫做信号的未决     (3) 阻塞: 进程可以选择阻塞某个信号, 被阻塞的信号产生时将保持在未决状态, 直到进程解除该信号的屏蔽, 才…

POJ 1511 Invitation Cards——Dijkstra优先队列优化+反向建图

【题目描述】 In the age of television, not many people attend theater performances. Antique Comedians of Malidinesia are aware of this fact. They want to propagate theater and, most of all, Antique Comedies. They have printed invitation cards with all the…

链栈 尹成

http://blog.csdn.net/itcastcpp/article/details/39271661 今天&#xff0c;我们一起用C写链栈&#xff0c;具体如下。 LinkStack.h具体内容&#xff1a; [cpp] view plaincopy #include "StackNode.h" template<typename Type> class LinkStack{ publ…

信号的捕捉以及SIGCHLD信号

一. 信号的捕捉定义 用户提供一个处理函数, 要求内核在处理信号时必须切换到用户态,执行这个函数, 这种方式就叫做信号的捕捉 二. 图解信号的捕捉过程 1. 由上图可以看出,当处理信号的执行动作时用户自定义的时候,此时就需返回该函数去调用该函数, 这就叫做信号的捕捉. 以前我…

链队 尹成

http://blog.csdn.net/itcastcpp/article/details/39271691 今天&#xff0c;我们一起用C写一个链对&#xff0c;具体如下所示。 LinkQueue.h具体内容如下&#xff1a; [cpp] view plaincopy #include "QueueNode.h" template<typename Type> class LinkQueu…

强连通分量入门——Trajan算法

今天学习了强连通分量。 【参考博客】 如果觉得我讲的有些地方难以理解或者存在问题&#xff08;欢迎留言&#xff09;&#xff0c;可以看一下我借鉴的一些大佬的博客&#xff1a; 传送门1 传送门2 【知识储备】 首先我们需要对几个定义有一些概念&#xff1a; 强连通&#xff…

最小栈的实现

所谓最小栈, 就是当前栈顶元素最小, 我们可以这样做, 每次在入栈之前, 将待入栈元素与栈顶元素相比, 每次现将待入栈的元素先入栈, 再将带入栈的元素和较小的元素入栈, 这样就可以保证每次栈顶元素是最小元素. 在出栈的时候规定每次出栈两个元素,这样就可以保证在出栈之后栈顶元…

用C++实现单链表的创建、逆置和输出 的两种方法

http://blog.csdn.net/lfeng_coding/article/details/47300563 题目描述&#xff1a;在已知单链表头节点的情况下&#xff0c;设计算法逆置单链表并输出 方法一&#xff1a;采用首先将头节点指向空&#xff0c;让其变为尾节点&#xff0c;然后利用中间节点 p、q 将其后的节点一…

两个栈实现一个队列

利用两个栈实现一个队列思路是这样的. 首先这个队列包含两个栈, 然后一个栈用来入队列, 一个栈用来出队列 typedef struct QueBy2Stack {SeqStack input;SeqStack output; }QueBy2Stack; 1. 初始化 void QueBy2StackInit(QueBy2Stack* stack) {if(stack NULL){return;//非法…

HDU 5934:Boom——强连通分量+缩点

【题目描述】 There are N bombs needing exploding.Each bomb has three attributes: exploding radius ri, position (xi,yi) and lighting-cost ci which means you need to pay ci cost making it explode.If a un-lighting bomb is in or on the border the exploding ar…

Linux--线程死锁

http://blog.csdn.net/gebushuaidanhenhuai/article/details/73799824 线程为什会死锁&#xff1f;&#xff1f;“锁”又是什么东西&#xff1f;我们这篇博客主要讲一下为什么要给线程加锁&#xff0c;为什么会出现线程死锁&#xff0c;线程死锁怎么解决。 互斥锁 在我的上篇博…

两个队列实现一个栈

用两个队列实现一个栈的原理是这样的. 规定两个队列, 必须有一个队列是非空, 一个队列是空.每次入栈时必须往非空队列中入, 而每次出栈时, 必须将非空队列里的元素装到空队列中, 直到非空队列中只有一个元素时, 此时就将剩下的这个元素出栈即可. 而取栈顶元素时, 和出栈一样, 先…

POJ-1144 Network——Trajan+割点

【题目描述】 A Telephone Line Company (TLC) is establishing a new telephone cable network. They are connecting several places numbered by integers from 1 to N . No two places have the same number. The lines are bidirectional and always connect together tw…

Linux--生产者与消费者

http://blog.csdn.net/gebushuaidanhenhuai/article/details/74011636 基本概念 提到生产者和消费者&#xff0c;我们最有可能想到的是商店卖东西&#xff0c;顾客在货架上(缓冲区&#xff09;买东西。 生产者消费者问题&#xff0c;其实是一个多线程同步问题的经典案例。该问…

进程的挂起以及可重入函数

相关接口     pause 函数用于将进程挂起. 如果信号的处理动作是终止进程, 则进程终止, pause 函数没有返回值; 如果信号的处理动作是忽略, 则进程被挂起, pause函数不返回, 如果信号的处理动作是捕捉, 则调用信号处理动作之后pause 返回 -1.来看一段代码 #include<s…

POJ1236Network of Schools——强连通分量缩点建图

【题目描述】 A number of schools are connected to a computer network. Agreements have been developed among those schools: each school maintains a list of schools to which it distributes software (the “receiving schools”). Note that if B is in the distri…

C——通过调用函数分配内存

http://blog.csdn.net/u012627502/article/details/3579724 1&#xff09;以返回值方式返回&#xff1a;把动态分配的存储位置地址&#xff0c;赋值给指针类型返回值&#xff08;不同于被调用函数的自动变量地址&#xff09; 2&#xff09;以形参形式返回&#xff1a;二级指针类…

gdb调试多进程程序

1.gdb下调试多进程程序只需要以下几条命令即可              除此之外还可以查看正在调试的进程 info inferiors, 同时也可以将当前正在调试的进程切换到另外一个进程中让其取运行     2.代码调试演示 #include<stdio.h> #include<stdlib.h> #…