目录
一、单向循环链表
1.1 单向循环链表的概念
1.单向循环链表:尾节点的指针域指向头结点的地址
2.单向循环链表的节点:数据域和指针域
数据域:存储的数据元素
指针域:存储节点之间的关系,下一个节点的地址,单向循环链表的指针域指向该节点的地址
1.2 单向循环链表的操作
1.2.1 单向循环链表的创建
// 创建单向循环链表---------------
Linklist creat_node()
{
// 1.创建一个新的节点
Linklist s=(Linklist)malloc(sizeof(struct Node));
// 2.
if(NULL==s)
return NULL;
// 初始化新节点的数据域
s->data=0;
// 初始化新节点的指针域
s->next=s;
return s;
}
1.2.2 单向循环链表的头插
// 头插---------------
Linklist insert_head(Linklist head,datatype element)
{
Linklist s=creat_node();
s->data=element;
// 1.判断链表是否为空
if(NULL==head)
head=s;
else // 链表中存在多个节点 >=1
{
// 找到尾节点
Linklist del=head;
while(del->next!=head)
{
del=del->next;
}
s->next=head;
head=s;
del->next=head;
}
return head;
}
1.2.3 单向循环链表的遍历
// 循环遍历---------------
void output(Linklist head)
{
// 1.判断链表是否为空
if(NULL==head)
return;
// 2.循环遍历
Linklist p=head;
printf("Linklist=");
do
{
printf("%d ",p->data);
p=p->next;
}while(p!=head);
putchar(10);
return;
}
1.2.4 单向循环链表的头删
// 单向循环链表的头删---------------
Linklist delete_head(Linklist head)
{
// 1.判断链表是否为空
if(NULL==head)
return head;
// 2.判断链表是否为1
if(head->next==head)
{
free(head);
head=NULL;
return head;
}
// 3.头删
// 找到尾节点
Linklist real=head;
while(real->next!=head)
{
real=real->next;
}
Linklist del;
del=head;
head=head->next;
free(del);
del=NULL;
real->next=head;
return head;
}
1.2.5 单向循环链表的尾插
// 单向循环链表的尾插---------------
Linklist insert_tail(Linklist head,datatype element)
{
// 1.创建新节点,并输入值
Linklist s=creat_node();
s->data=element;
s->next=head;
// 2.判断链表是否为空
if(NULL==head)
{
head=s;
}
else
{
// 3.尾插
Linklist p=head;
while(p->next!=head) // 找到最后一个节点
{
p=p->next;
}
p->next=s; // 链接:p指针域指向新节点的地址
}
return head;
}
1.2.6 单向循环链表的尾删
// 单向循环链表的尾删---------------
Linklist delete_tail(Linklist head)
{
// 1.判断链表是否为空
if(NULL==head)
return head;
// 2.只有一个节点时
else if(head->next==head)
{
free(head);
head=NULL;
}
// 3.有多个节点时
else
{
Linklist del=head;
// 找到倒数第二个节点
while(del->next->next!=head)
{
del=del->next;
}
// 删除p的后继
free(del->next);
del->next=head;
}
return head;
}
1.2.7 约瑟夫环
约瑟夫环:用循环链表编程实现约瑟夫问题
n个人围成一圈,从某人开始报数1, 2, …, m,数到m的人出圈,然后从出圈的下一个人(m+1)开始重复此过程,直到 全部人出圈,于是得到一个出圈人员的新序列
如当n=8,m=4时,若从第一个位置数起,则所得到的新的序列 为4, 8, 5, 2, 1, 3, 7, 6。
// 约瑟夫环
Linklist joseph(Linklist head,int n, int m)
{
Linklist p=head;
Linklist del=NULL;
Linklist s=NULL;
for(int i=1;i<=n;i++)
{
for(int j=1;j<m-1;j++)
{
p=p->next;
}
del=p->next;
p->next=p->next->next;
p=p->next;
if(i==1)
{
head=del;
head->next=head;
}
else
{
s=head;
while(s->next!=head)
{
s=s->next;
}
del->next=head;
s->next=del;
}
}
return head;
}
1.3 单向循环列表所有程序
1.3.1 head.h
#ifndef __HEAD_H__
#define __HEAD_H__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef int datatype;
enum passble{SUCCSSES,FALSE=-1};
// 节点结构定义
// 节点:数据、指针域
// Node不可省略
typedef struct Node
{
datatype data; // 数据域:数据元素
struct Node *next; // 指针域:节点之间的关系,下一个节点的地址
}*Linklist;
Linklist creat_node();
Linklist insert_head(Linklist head,datatype element);
void output(Linklist head);
Linklist delete_head(Linklist);
Linklist insert_tail(Linklist head,datatype element);
Linklist delete_tail(Linklist head);
int get_len(Linklist head);
Linklist joseph(Linklist head,int n, int m);
#endif
1.3.2 main.c
#include "head.h"
int main(int argc, const char *argv[])
{
// 单向循环链表的创建
// 单向循环链表的头插
Linklist head=NULL;
int n;
printf("请输入插入个数:");
scanf("%d",&n);
datatype element;
for(int i=0;i<n;i++)
{
printf("请输入插入的第 %d 个元素:",i+1);
scanf("%d",&element);
head=insert_head(head,element);
}
output(head);
// 单向循环链表的头删
head=delete_head(head);
printf("头删后");
output(head);
// 单向循环链表的尾插
printf("请输入尾插个数:");
scanf("%d",&n);
for(int i=0;i<n;i++)
{
printf("请输入尾插元素:");
scanf("%d",&element);
head=insert_tail(head,element);
}
output(head);
// 单向循环链表的尾删
head=delete_tail(head);
printf("尾删后");
output(head);
// 约瑟夫环
int m=4;
head=joseph(head,n,m);
output(head);
return 0;
}
1.3.3 fun.c
#include "head.h"
// 创建单向循环链表---------------
Linklist creat_node()
{
// 1.创建一个新的节点
Linklist s=(Linklist)malloc(sizeof(struct Node));
// 2.
if(NULL==s)
return NULL;
// 初始化新节点的数据域
s->data=0;
// 初始化新节点的指针域
s->next=s;
return s;
}
// 头插---------------
Linklist i