Linux C 数据结构—-循环链表

前面我们学习了单向链表,现在介绍单向循环链表,单向循环链表是单链表的一种改进,若将单链表的首尾节点相连,便构成单向循环链表结构,如下图:


     对于一个循环链表来说,其首节点和末节点被连接在一起。这种方式在单向和双向链表中皆可实现。要转换一个循环链表,可以选择开始于任意一个节点然后沿着列表的任一方向直到返回开始的节点。再来看另一种方法,循环链表可以被视为“无头无尾”。这种列表很利于节约数据存储缓存, 假定你在一个列表中有一个对象并且希望所有其他对象迭代在一个非特殊的排列下。指向整个列表的指针可以被称作访问指针。
    循环链表中第一个节点之前就是最后一个节点,反之亦然。循环链表的无边界使得在这样的链表上设计算法会比普通链表更加容易。对于新加入的节点应该是在第一个节点之前还是最后一个节点之后可以根据实际要求灵活处理,区别不大。当然,如果只会在最后插入数据(或者只会在之前),处理也是很容易的。
      
      循环链表的应用

一、Joseph问题(约瑟夫环)

     据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人找到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。 

     约瑟夫环用数学问题来描述就是:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。如何用循环链表来求解Josephu问题?

    下面我们用单向循环链表来模拟这个问题:

[cpp] view plaincopy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3.   
  4. typedef int data_t;  
  5.   
  6. typedef struct node_t  
  7. {  
  8.     data_t data;  
  9.     struct node_t *next;      
  10. }linknode_t,*linklist;  
  11.   
  12. linklist CreateList(int n)  
  13. {  
  14.     int i;  
  15.     linklist p,head,tail;  
  16.     head = NULL;  
  17.       
  18.     for(i = 1;i <= n;i++)  
  19.     {  
  20.         p = (linklist)malloc(sizeof(linklist));  
  21.         if(p == NULL)  
  22.         {  
  23.             printf("malloc fails!\n");  
  24.         }  
  25.               
  26.         p->data = i;  
  27.         if(head == NULL)  
  28.         {  
  29.             head = p;  
  30.             tail = head;  
  31.         }  
  32.         else  
  33.         {  
  34.             tail->next = p;  
  35.         }                 
  36.           
  37.         tail = p;  
  38.     }  
  39.       
  40.     tail->next = head;  
  41.   
  42.     return head;   
  43. }  
  44.   
  45. void Joseph(int n,int k,int m)  
  46. {  
  47.     int i;  
  48.     linklist p,r;  
  49.     p = CreateList(n);  
  50.   
  51.     for(i = 1;i < k;i++) //从第K个人开始数  
  52.     {  
  53.         p = p->next;  
  54.     }  
  55.   
  56.     while(p->next != p)  
  57.     {  
  58.         for(i = 1;i <= m-2;i++)  //数到第m个人,去自杀  
  59.             p = p->next;  
  60.   
  61.         r = p->next;  
  62.         p->next = r->next;  
  63.         printf("%d->",r->data);  
  64.           
  65.         free(r);  
  66.         p = p->next;//从下一个人继续数  
  67.     }  
  68.       
  69.     printf("%d\n",p->data);  
  70. }  
  71.   
  72. int main()  
  73. {  
  74.     Joseph(41,1,3);  
  75.   
  76.     return 0;  
  77. }  
输出结果如下:
[cpp] view plaincopy
  1. fs@ubuntu:~/qiang/linklist$ ./list1  
  2. 3->6->9->12->15->18->21->24->27->30->33->36->39->1->5->10->14->19->23->28->32->37->41->7->13->20->26->34->40->8->17->29->38->11->25->2->22->4->35->16->31  
我们可以看到,最后两个是16和31,这样,约瑟夫和他的朋友就躲过了一劫!


二、判断一个链表是不是循环链表(如何判定这个链表当中是否包含有环路

 解决方法:

      判断是否是循环链表时,也设置两个指针,慢指针和快指针,让快指针比慢指针每次移动快两次。如果快指针追赶上慢指针,则为循环链表,否则不是循环链表,如果快指针或者慢指针指向NULL,则不是循环链表。

代码如下:

[cpp] view plaincopy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3.   
  4. typedef int data_t;  
  5.   
  6. typedef struct node_t  
  7. {  
  8.     data_t data;  
  9.     struct node_t *next;      
  10. }linknode_t,*linklist;  
  11.   
  12. linklist CreateList(int n)  
  13. {  
  14.     int i;  
  15.     linklist p,head,tail;  
  16.     head = NULL;  
  17.       
  18.     for(i = 1;i <= n;i++)  
  19.     {  
  20.         p = (linklist)malloc(sizeof(linklist));  
  21.         if(p == NULL)  
  22.         {  
  23.             printf("malloc fails!\n");  
  24.         }  
  25.               
  26.         p->data = i;  
  27.         if(head == NULL)  
  28.         {  
  29.             head = p;  
  30.             tail = head;  
  31.         }  
  32.         else  
  33.         {  
  34.             tail->next = p;  
  35.         }                 
  36.           
  37.         tail = p;  
  38.     }  
  39.       
  40.     tail->next = head;  
  41.   
  42.     return head;   
  43. }  
  44.   
  45. int JudgeIsloop(linklist list)  
  46. {  
  47.     int flag = 0;  
  48.     linknode_t *slow,*fast;  
  49.   
  50.     if(list == NULL)  
  51.         return 0;  
  52.   
  53.     slow = list;  
  54.     fast = list->next;  
  55.   
  56.     while(slow)  
  57.     {  
  58.         if(fast == NULL || fast->next == NULL)//走到头了  
  59.             return 0;  
  60.         else if(fast == slow || fast->next == slow)//二者相遇,因为fast走的快,如果fast->next指向slow,也是循环的  
  61.         {     
  62.             flag = 1;  
  63.             return 1;  
  64.         }  
  65.         else  
  66.         {  
  67.             slow = slow->next;//慢指针走一步  
  68.             fast = fast->next->next;//快指针走两步  
  69.         }  
  70.     }  
  71.   
  72.     return 0;  
  73. }  
  74.   
  75. int main()  
  76. {  
  77.     int i;  
  78.     int flag = 0;  
  79.     linklist list;  
  80.     list = CreateList(10);  
  81.       
  82.     JudgeIsloop(list);  
  83.   
  84.     if(flag = 0)  
  85.         printf("The list is not a looplist!\n");  
  86.     else  
  87.     {  
  88.         printf("The list is a looplist!\n");//循环链表则打印出来  
  89.         for(i = 0;i < 10;i++)  
  90.         {  
  91.             printf("%d->",list->data);  
  92.             list = list->next;  
  93.         }  
  94.         printf("%d\n",list->data);  
  95.     }  
  96.   
  97.     return 0;  
  98. }  
结果如下:

[cpp] view plaincopy
  1. fs@ubuntu:~/qiang/linklist$ ./list2  
  2. The list is a looplist!  
  3. 1->2->3->4->5->6->7->8->9->10->1  
  4. fs@ubuntu:~/qiang/linklist$ 

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

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

相关文章

预备作业03 20162320刘先润

第一次编代码 这几周自学了Linux基础入门&#xff0c;有好多想吐槽的地方&#xff0c;所以这篇随笔是带有半吐槽性质的&#xff0c;这是我学完后最真实的感受 我在电脑上按照教程安装了虚拟机&#xff0c;对于Linux这个完全陌生的概念也稍微算是有些理解&#xff0c;但是还有很…

JTable 失去焦点时取消编辑状态

为什么80%的码农都做不了架构师&#xff1f;>>> reference&#xff1a; http://tips4java.wordpress.com/2008/12/12/table-stop-editing/ 当JTable的单元格处于编辑状态时&#xff0c;如果用户触发以下事件&#xff0c;表格就会退出编辑状态&#xff0c;进而调用T…

Linux C 数据结构——栈

还是先把这张图贴出来&#xff0c;以便对比和理解 栈是限制在一段进行插入操作和删除操作的线性表&#xff08;俗称堆栈&#xff09;&#xff0c;允许进行操作的一端称为“栈顶”&#xff0c;另一固定端称为“栈底”&#xff0c;当栈中没有元素称为“空栈”。特点&#xff1a;先…

常用的HTTP状态码

2019独角兽企业重金招聘Python工程师标准>>> 第一、成功的状态码&#xff1a; 1&#xff09;200 OK – 服务器成功返回网页 2&#xff09;304 Not Modified – 未修改 第二、失败的状态码&#xff1a; 3&#xff09;404 Not F…

Linux C 数据结构——队列

还是先放这张图&#xff0c;以便对比和理解&#xff1a; 队列是限制在两端进行插入操作和删除操作的线性表&#xff0c;允许进行存入操作的一端称为“队尾”&#xff0c;允许进行删除操作的一端称为“队头”。当线性表中没有元素时&#xff0c;称为“空队”。特点&#xff1a;先…

如何使用FF的Firebug组件中的net工具查看页面元素加载消耗时间

1.安装FF的Firebug组件&#xff1a;点击FF的Tools的Add-ons菜单&#xff0c;输入Firebug关键字&#xff0c;并选择合适的版本Install。 2.安装完毕后地址栏右边会出现一个小虫图标&#xff0c;右边还有一个下拉箭头。如下图&#xff1a; 3.点击下拉箭头&#xff0c;选择“on fo…

Linux C 数据结构——二叉树

先放这张图&#xff1a; 可以看出&#xff0c;树是非线性结构&#xff1b; 一、树的概念 树&#xff08;tree&#xff09;是n(n>0)个节点的有限集合T&#xff0c;它满足两个条件&#xff1a; 1&#xff09;有且仅有一个特定的称为根&#xff08;root&#xff09;的节点&…

Linux C 算法——查找

所谓“查找”记为在一个含有众多的数据元素&#xff08;或记录&#xff09;的查找表中找出某个“特定的”数据&#xff0c;即在给定信息集上寻找特定信息元素的过程。 为了便于讨论&#xff0c;必须给出这个“特定的”词的确切含义。首先&#xff0c;引入一个“关键字”的概念&…

SharePoint项目中新建类库的错误处理及项目建设中遇到的问题总结

第一次SP项目总监遇到各种问题&#xff0c;以下是总结&#xff1a;问题1.创建SP项目的时候“场解决方案”跟“沙盒解决方案”是有区别的&#xff0c;具体可以看MSDN官方文档&#xff0c;这里简单摘抄如下&#xff1a;1&#xff09;场解决方案&#xff1a;承载与W3WP.exe中&…

ECharts学习(1)--简单图表的绘制

1.获取ECharts 官网 下载&#xff1a;http://echarts.baidu.com/download.html 2.在html页面中引入ECharts文件 <!DOCTYPE html> <html><head><meta charset"UTF-8"><title>ECharts练习</title><script type"text/javas…

Linux C 算法——排序

排序(Sort)是将无序的记录序列&#xff08;或称文件&#xff09;调整成有序的序列。 为了方便讨论&#xff0c;在此首先要对排序下一个确切的定义&#xff1a; 假设含有n个记录的序列为 { R1、R2、&#xff0c;。。。Rn } 其相应的关键字序列为 {K1、K2&#xff0c;。。。。Kn}…

JSON.parse 解析json字符串时,遇换行符报错

Json字符串转换成Json对象时候&#xff0c;有两种方式&#xff1a; 假设d是json字符串&#xff1a; 1&#xff0c;eval(( d ))。 2&#xff0c;JSON.parse(d)&#xff1b; 但是以上方式有隐患&#xff0c;如果Json字符串有换行的话&#xff0c;这样转换就会报错。 假如有…

文件I/O和标准I/O的区别

一、先来了解下什么是文件I/O和标准I/O&#xff1a; 文件I/O&#xff1a;文件I/O称之为不带缓存的IO&#xff08;unbuffered I/O)。不带缓存指的是每个read&#xff0c;write都调用内核中的一个系统调用。也就是一般所说的低级I/O——操作系统提供的基本IO服务&#xff0c;与os…

程序集、应用程序配置及App.config和YourSoft.exe.config .

转自&#xff1a;http://www.cnblogs.com/luminji/archive/2010/10/21/1857339.html 什么是程序集 程序集标识属性 强名称的程序集 强名称工作原理配置文件使用 DEVPATH 查找程序集指定要使用的运行库版本Appconfig和YourSoftexeconfig本章概要&#xff1a; 1&#xff1a;什么是…

[Android]在Dagger 2中使用RxJava来进行异步注入(翻译)

以下内容为原创&#xff0c;欢迎转载&#xff0c;转载请注明 来自天天博客&#xff1a;http://www.cnblogs.com/tiantianbyconan/p/6236646.html 在Dagger 2中使用RxJava来进行异步注入 原文&#xff1a;http://frogermcs.github.io/async-injection-in-dagger-2-with-rxjava 几…

关于Go语言在服务端做Restful接口和socket通信

请到我的个人博客看golang rest相关文章 http://xiaorui.cc关于Go语言在服务端做Restful接口和socket通信已经转到: http://xiaorui.cc/2014/10/25/%E5%85%B3%E4%BA%8Ego%E8%AF%AD%E8%A8%80%E5%9C%A8%E6%9C%8D%E5%8A%A1%E7%AB%AF%E5%81%9Arestful%E6%8E%A5%E5%8F%A3%E5%92%8C…

UVa 11136 - Hoax or what

题目大意&#xff1a;超市进行促销活动&#xff0c;顾客可以把账单放到一个箱子里&#xff0c;每天超市会从箱子中抽出最高消费者和最低消费者&#xff0c;最高消费者可以得到&#xff08;最高消费-最低消费&#xff09;的金钱。询问超市在n天的促销活动结束后应支付多少钱。 找…

Winfrom实现圆角设计

主要代码 public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Paint(object sender, PaintEventArgs e) { Type(this, 25, 0.1); } private void…

Linux 系统应用编程——进程基础

一、Linux下多任务机制的介绍 Linux有一特性是多任务&#xff0c;多任务处理是指用户可以在同一时间内运行多个应用程序&#xff0c;每个正在执行的应用程序被称为一个任务。 多任务操作系统使用某种调度(shedule)策略&#xff08;由内核来执行&#xff09;支持多个任务并发执行…