老样子,先创建好结构体
typedef int datatype;
typedef struct Node
{
union
{
datatype data; //节点数据域
int len; //长度
};
struct Node *next; //指针域
}Looplink;
辅助函数:
创建链表头函数:
//创建
Looplink *list_create()
{
Looplink *L=(Looplink*)malloc(sizeof(Looplink));
if(NULL == L)
{
printf("创建失败\n");
return NULL;
}
//初始化
L->len=0;
L->next=L; //初始化时,头节点的指针域指向自己
printf("创建成功\n");
return L;
}
以及一部分辅助函数
//判空
int list_empty(Looplink *L)
{
return L->next==L? 1:0; //1表示空 0表示非空
}
//节点申请函数
Looplink* node_add(datatype e)
{
Looplink *p = (Looplink*)malloc(sizeof(Looplink));
if(NULL == p)
{
printf("节点申请失败\n");
return NULL;
}
//数据存放
p->data = e;
p->next = NULL;
}
在主函数引导指定总数与步长,并存入循环链表
int m,n;
printf("请制定数据总数:");
scanf("%d",&m);
printf("去指定选择步长:");
scanf("%d",&n);
Looplink *L = list_create(); //创建循环单向链表
for(int i=0; i
然后为了避免头节点影响遍历步长,故删除头节点
//删除头节点,使循环链表变成约瑟夫环
Looplink *p = kill_head(L); //删除头节点函数
//遍历
list_show2(p);
/****************以下是用到的函数块*********************/
//链表断头
Looplink *kill_head(Looplink *L)
{
//判断逻辑
if(NULL==L || list_empty(L))
{
printf("删除失败\n");
return NULL;
}
//定义遍历指针定位到最后一个节点
Looplink *q = L->next;
while(q->next != L)
{
q=q->next;
}
//孤立头结点
q->next=L->next;
//删除头节点
free(L);
L=NULL;
//返回第一个节点的位置
printf("头结点删除成功\n");
return q->next;
}
/***************************************/
//删除头节点的遍历
void list_show2(Looplink *S)
{
//判断逻辑
if(NULL==S)
{
printf("遍历失败\n");
return ;
}
//遍历
printf("链表元素分别是\n");
Looplink *q=S;
do
{
printf("%d\t",q->data);
q=q->next;
}while(q!=S);
printf("\n");
}
创建一个新的头,用以接受拆出来的链表元素
//创建一个新的头:S
Looplink *S = list_create();
接下来,我们需要用指针p遍历链表,每四步断一次,然后把选中的元素,嫁接到新的链表头S上。同时要注意,
重要的事情说三遍,不然会导致指针p指到只有一个元素的链表S内,导致段错误。故,应当设一个局部变量q,让它指向p,代替p进入嫁接函数。
//循环取值,逢n取1,到只剩一值时停下
for(int i=0; inext;
}
Looplink *q = p; //工具人,让它去被拆掉,如果把p丢入函数,
//会导致p指向只有一个元素的链表S,从而导致段错误
p = p->next;
list_reverse(S, q); //拆除嫁接函数
}
list_reverse(S, p); //把最后剩下的数嫁接到S上
/*******************以下是使用到的相关函数***********************/
//拆出链表并嫁接
void list_reverse(Looplink *S ,Looplink *p)
{
//查找前一个节点
Looplink *q = find_node(p); //前节点查找函数
//孤立p
q->next = p->next;
p->next = NULL;
//尾插法把p插入S
Looplink *k=S;
while(k->next != S)
{
k=k->next;
}
p->next = S;
k->next = p;
//
S->len++;
printf("尾插成功\n");
}
/********************上一个函数用到的节点查找函数************/
//查找上一个结点
Looplink *find_node(Looplink *L)
{
//查找节点
Looplink *q = L;
while(q->next != L) //当q下一位是L时停止
{
q = q->next;
}
return q; //返回找到的节点
}
此时,我们已经得到了一个新的循环链表,只需要断掉最后一个元素与头节点S的连接,就能得到一个崭新出厂的顺序链表S了
//断开S与最后一位的链接
Looplink *q=S;
while(q->next != S)
{
q = q->next;
}
q->next = NULL;
//遍历S,检验结果
list_show(S);
return 0;
/**********************顺序链表的遍历函数*******************/
//遍历
void list_show(Looplink *L)
{
if(NULL == L || list_empty(L)) //先判断非法
{
printf("表空或表非法,遍历失败\n");
return;
}
//遍历
printf("链表元素为:");
Looplink *q = L->next;
while(q != NULL)
{
printf("%d\t",q->data);
q = q->next;
}
printf("\n");
}
至此,我们便完成了这个问题
以下张贴完整代码,酌情观看。
/**********************main.c********************/
//主函数
#include
#include
#include"ysf.h"
int main(int argc, const char *argv[])
{
int m,n;
printf("请制定数据总数:");
scanf("%d",&m);
printf("去指定选择步长:");
scanf("%d",&n);
Looplink *L = list_create(); //创建循环单向链表
for(int i=0; inext;
}
Looplink *q = p; //工具人,让它去被拆掉
p = p->next;
list_reverse(S, q);
}
list_reverse(S, p);
//断开S与最后一位的链接
Looplink *q=S;
while(q->next != S)
{
q = q->next;
}
q->next = NULL;
//遍历S,检验结果
list_show(S);
return 0;
}
功能函数文件
/**********************ysf.h*******************/
#include
#include
#include"ysf.h"
//创建
Looplink *list_create()
{
Looplink *L=(Looplink*)malloc(sizeof(Looplink));
if(NULL == L)
{
printf("创建失败\n");
return NULL;
}
//初始化
L->len=0;
L->next=L; //初始化时,头节点的指针域指向自己
printf("创建成功\n");
return L;
}
//判空
int list_empty(Looplink *L)
{
return L->next==L? 1:0; //1表示空 0表示非空
}
//节点申请函数
Looplink* node_add(datatype e)
{
Looplink *p = (Looplink*)malloc(sizeof(Looplink));
if(NULL == p)
{
printf("节点申请失败\n");
return NULL;
}
//数据存放
p->data = e;
p->next = NULL;
}
//查找上一个结点
Looplink *find_node(Looplink *L)
{
//查找节点
Looplink *q = L;
while(q->next != L)
{
q = q->next;
}
return q; //返回找到的节点
}
//循环链表的尾插法
int list_insert_tail(Looplink *L,datatype e)
{
//判断
if(NULL==L)
{
printf("所给链表不合法\n");
return -1;
}
//申请节点
Looplink *p = node_add(e);
//插入逻辑
Looplink *q=L;
while(q->next != L)
{
q = q->next;
}
p->next=L;
q->next=p;
//表的变化
L->len++;
printf("尾插成功\n");
}
//链表断头
Looplink *kill_head(Looplink *L)
{
//判断逻辑
if(NULL==L || list_empty(L))
{
printf("删除失败\n");
return NULL;
}
//定义遍历指针定位到最后一个节点
Looplink *q = L->next;
while(q->next != L)
{
q=q->next;
}
//孤立头结点
q->next=L->next;
//删除头节点
free(L);
L=NULL;
//返回第一个节点的位置
printf("头结点删除成功\n");
return q->next;
}
//拆出链表并嫁接
void list_reverse(Looplink *S ,Looplink *p)
{
//查找前一个节点
Looplink *q = find_node(p);
//孤立
q->next = p->next;
p->next = NULL;
//尾插法把p插入S
Looplink *k=S;
while(k->next != S)
{
k=k->next;
}
p->next = S;
k->next = p;
//
S->len++;
printf("尾插成功\n");
}
//遍历
void list_show(Looplink *L)
{
if(NULL == L || list_empty(L)) //先判断非法
{
printf("表空或表非法,遍历失败\n");
return;
}
//遍历
printf("链表元素为:");
Looplink *q = L->next;
while(q != NULL)
{
printf("%d\t",q->data);
q = q->next;
}
printf("\n");
}
//删除头节点的遍历
void list_show2(Looplink *S)
{
//判断逻辑
if(NULL==S)
{
printf("遍历失败\n");
return ;
}
//遍历
printf("链表元素分别是\n");
Looplink *q=S;
do
{
printf("%d\t",q->data);
q=q->next;
}while(q!=S);
printf("\n");
}
最后是头文件
#ifndef __YSF__
#define __YSF__
typedef int datatype;
typedef struct Node
{
union
{
datatype data; //节点数据域
int len; //长度
};
struct Node *next; //指针域
}Looplink;
//创建
Looplink *list_create();
//查找上一个节点
Looplink *find_node(Looplink *L);
//判空
int list_empty(Looplink *L);
//节点申请函数
Looplink* node_add(datatype e);
//尾插
int list_insert_tail(Looplink *L,datatype e);
//链表断头
Looplink *kill_head(Looplink *L);
//拆出链表并嫁接
void list_reverse(Looplink *S ,Looplink *p);
//遍历
void list_show(Looplink *L);
//删除头节点的遍历
void list_show2(Looplink *S);
#endif