七、线性表(4)
来源:互联网 发布:东北师大网络教育学院 编辑:程序博客网 时间:2024/04/29 15:19
循环链表
1、定义
将单链表中终端结点的指针端由空指针改为指向头结点,就使整个单链表形成一个环,这种头尾相接的单链表成为单循环链表,简称循环链表。
实现代码分为四部分:
初始化、插入、删除、返回结点所在位置。
2、约瑟夫问题
据说著名犹太历史学家约瑟夫有过以下的故事:
在罗马人占领桥塔帕特后,41个犹太人决定了一个自杀方式,41个人排成一个圆圈,由第一个人开始报数,每报数到第3人,该人就必须自杀,然后再由下一个人重新报数,直到所有人都自杀身亡为止。
代码:用循环链表模拟约瑟夫问题,把41个人自杀的顺序编号输出。
//n个人围圈报数,报m出列,最后剩下的是几号?#include <stdio.h>#include <stdlib.h>typedef strue node { int data;//数据 struct node *next;//指向下一个位置的指针}node;node *create(int n)//创建链表{ node *p=NULL,*head; head=(node*)malloc(sizeof(node));//定义头结点 p=head;//p是指向当前结点的指针 node *s; int i=1; if(0!=n) { while(i<=n) { s=(node *)malloc(sizeof(node)); s->data=i++;//为循环链表初始化,第一个结点为1,第二个结点为2. p->next=s; p=s; } s->next=head->next;//最后一个结点指向第一个结点 }free(head);//释放头结点return s->next;//返回指向头结点的地址}int main(){ int n=41; int m=3; int i; node *p=create(n);//p是指向循环链表第一个结点的指针 node *temp;//临时指针 m%=n; while(p!=p->next)//不是空表的时候循环 { for(i=1;i<m-1;i++) { p=p->next; } printf("%d->",p->next->data); temp=p->next;//删除第m个结点 p->next=temp->next; free(temp); p=p->next; } printf("&d\n",p->data); return 0;}
循环链表的特点
判断是否为空链表的条件:即判断rear是否等于rear->next。
循环链表的特点是无须增加存储量,仅对链接方式稍作改变,即可使得表处理更加方便灵活。
实现将两个线性表(a1,a2,….,an)和(b1,b2,…,bm)连接成一个线性表(a1,a2,….,an,b1,b2,…,bm)的运算。
//假设A,B为非空循环链表的尾指针LinkList Connect(LinkList A,LinkList B){ LinkList p=A->next;//保存A表的头结点位置 A->next=B->next->next;//B表的开始结点链接到A表尾 free(B->next);//释放B表的头结点 B->next=p; return B;//返回新循环链表的尾指针}
判断单链表中是否有环
有环的定义是,链表的尾结点指向了链表中的某个节点。
判断:
- 方法一:使用p,q两个指针,p总是向前走,但q每次都是从头开始走,对于每个节点,看p走的步数是否和q一样。
- 方法二:使用p,q两个指针,p每次向前走一步,q每次向前走两步,若在某个时候p==q,则存在环。
3、魔术师发牌问题
问题描述:
魔术师利用一副牌中的13张黑牌,预先将他们排好后叠放在一起,牌面朝下。对观众说:我不看牌,只数数就可以猜到每张牌是什么,我大声叔叔,你们听,不信?现场演示。
魔术师将最上面的那张牌数为1,把它翻过来正好是黑桃A,将黑桃A放在桌子上,第二次数1,2,将第一张牌放在这些牌的下面,将第二张牌翻过来,正好是黑桃2,也将他放在桌子上这样依次进行将13张牌全部翻出,准确无误。
请问:牌的开始顺序是如何安排的?
代码:
#include <stdio.h>#include <stdlib.h>#define CardNumber 13typedef struct node { int data; struct node *next;}sqlist,*linklist;linklist CreatLinkList(){ linklist head=NULL; linklist s,r; int i; r=head; for(i=1;i<=CardNumber;i++) { s=(linklist)malloc(sizeof(sqlist)); s->data=0; if(head==NULL) head=s; else r->next=s; r=s; } r->next=head; return head;}//发牌顺序计算void Magician(linklist head){ linklist p; int j; int Countnumber=2; p=head; p->data=1; while(1) { for(j=0;j<Countnumber;j++) { p=p->next; if(p->data!=0) { p->next; j--; } } if(p->data==0) { p->data=Countnumber; Countnumber++; if(Countnumber==14) break; } }} //销毁void DestoryList(linklist *list){ linklist ptr=*list; linklist buff[CardNumber]; int i=0; while (i<CardNumber) { buff[i++]=ptr; ptr=ptr->next; } for(i=0;i<CardNumber;++i) free(buff[i]); *list=0;} int main(){ linklist p; int i; p=CreatLinkList(); Magician(p); printf("按如下顺序排列:\n"); for(i=0;i<CardNumber;i++) { printf("黑桃%d",p->data); p=p->next; } DestoryList(&p); return 0;}
双向链表
typedef struct DualNode{ ElemType data; struct DualNode *prior;//前驱结点 struct DualNode *next;//后继结点}DualNode, *DuLinkList;
对于双向链表中的某一个结点P,它的后继结点的前驱结点是他自己。
双向链表的插入操作
代码实现:
- s->next=p;
- s->prior=p->prior;
- p->prior->next=s;
- p->prior=s;
双向链表的删除操作
- p->prior->next=p->next;
- p->next->prior=p->prior;
- free(p);
- 双向链表相对于单链表来说更复杂,每个结点多了一个prior指针。不过,双向链表可以提高算法的时间性能,即用空间来换取时间。
双向循环链表实践
要求实现用户输入一个数使得26个字母的排列发生变化,例如用户输入3,输出结果:
-DEFGHIJKLMNOPQRSTUVWXYZABC
同时需要支持负数,例如用户输入-3,输出结果:
-XYZABCDEFGHIJKLMNOPQRSTUVW
#include <stdio.h>#include <stdlib.h>#define OK 1#define ERROR 0typedef char ElemType;typedef int Status;typedef struct DualNode{ ElemType data; struct DualNode *prior; struct DualNode *next;}DualNode,*DuLinkList;Status InitList(DuLinkList *L){ DualNode *p,*q; int i; *L=(DuLinkList)malloc(sizeof(DualNode)); if(!(*L)) { return ERROR; } (*L)->next=(*L)->prior=NULL; p=(*L); for(i=0;i<26;i++) { q=(DualNode *)malloc(sizeof(DualNode)); if(!q) { return ERROR; } q->data='A'+i; q->prior=p; q->next=p->next; p->next=q; p=q; } p->next=(*L)->next; (*L)->next->prior=p; return OK;}void Caesar(DuLinkList *L,int i){ if(i>0) { do { (*L)=(*L)->next; }while (--i); } if(i<0) { do { (*L)=(*L)->next; }while(++i); }}int main(){ DuLinkList L; int i,n; InitList(&L); printf("请输入一个整数:"); scanf("%d",&n); printf("\n"); Caesar(&L,n); for(i=0;i<26;i++) { L=L->next; printf("%c",L->data); } printf("\n"); return 0;}
0 0
- 七、线性表(4)
- 数据结构(七)线性表(二)
- 数据结构七线性表
- Python OpenCV 线性滤波器 简介(七)
- Android线性布局LinearLayout(七)
- (七)线性堆栈
- 神经网络学习笔记(七):线性回归模型(上)
- 重新教自己学算法之线性队列(七)
- 9 线性表(4)
- 线性表学习(4)
- 模式识别(Pattern Recognition)学习笔记(七)——线性分类器及线性判别函数
- 模式识别(Pattern Recognition)学习笔记(七)——线性分类器及线性判别函数
- 数据结构实验之查找七:线性之哈希表(线性探测解决哈希表的冲突)
- SDUT 3379 数据结构实验之查找七:线性之哈希表(线性探测法解决冲突)
- 线性表线性(顺序)存储结构
- 线性结构------线性表(一)
- 线性结构------线性表(二)
- 线性表(线性存储结构)
- MyEclipse优化
- 房地产计算面积
- poj2935 Basic Wall Maze (2016xynu暑期集训检测 -----D题)
- html5 promise的使用
- Linux内存描述之内存节点node--Linux内存管理(二)
- 七、线性表(4)
- Java web项目中web.xml的配置
- git删除历史遗留大文件
- dexopt魔数验证
- [Codeforces Round #369 (Div. 2)D. Directed Roads]Tarjan强连通分量+组合计数
- 建议19:使用更有效的对象和集合初始化
- 十大算法展辉煌历史,十大问题引锦绣前程
- 探讨C++中对象的“浅拷贝”与“深拷贝”
- live555之openRTSP----- continueAfterDESCRIBE()