单向循环链表
单向循环链表的特点
单链表最后一个节点的next指针指向的NULL,但是单向循环链表的next指针指向了头节点,这样它就形成了一个环状的效果。通过这个环可以一直获取next的成员,而不用每次都记录h节点的位置。
单向循环链表的结构
#define datatype int
typedef struct node{
datatype data;
struct node *next;
}linklist_t;
单向循环链表的操作
单向循环链表的创建
looplink_t* LoopLinkCreate(void)
{
looplink_t *h;
h = (looplink_t *)malloc(sizeof(*h));
if(h == NULL){
printf("malloc head memory error\n");
return NULL;
}
h->data = (datatype)0;
h->next = h;
return h;
}
单向循环链表节点插入
单向循环链表头插法
int LoopLinkInsertHead(looplink_t* h, datatype data)
{
looplink_t* tmp;
tmp = (looplink_t*)malloc(sizeof(*tmp));
if (tmp == NULL) {
printf("malloc node memory error\n");
return -1;
}
tmp->data = data;
//进行头插法
tmp->next = h->next;
h->next = tmp;
return 0;
}
单向循环链表尾插法
int LoopLinkInsertTail(looplink_t* h, datatype data)
{
looplink_t* tmp;
looplink_t* th = h;
// 1.分配tmp节点,当data存入
tmp = (looplink_t*)malloc(sizeof(*tmp));
if (tmp == NULL) {
printf("malloc node memory error\n");
return -1;
}
tmp->data = data;
// 2.通过循环找到尾部节点
while(h->next != th){
h = h->next;
}
// 3.将节点插入到当前位置
tmp->next = h->next;
h->next = tmp;
return 0;
}
单向循环链位置插入
int LoopLinkInsertPos(looplink_t* h, int pos, datatype data)
{
looplink_t *tmp, *th = h;
// 1.判断pos是否合法
if (pos < 0) {
printf("插入的位置不合法\n");
return -1;
}
// 2.通过循环找出插入节点的位置
while (h->next != th || pos == 0) {
if (pos != 0) {
pos--;
h = h->next;
} else {
// 3.找到了插入节点的位置,将节点插入即可。
tmp = (looplink_t*)malloc(sizeof(*tmp));
if (tmp == NULL) {
printf("malloc memory error\n");
return -1;
}
tmp->data = data;
tmp->next = h->next;
h->next = tmp;
return 0;
}
}
printf("插入的位置不合法\n");
return -1;
}
单向循环链表的删除(位置)
datatype LoopLinkDeleteByPos(looplink_t* h, int pos)
{
datatype data;
looplink_t* tmp,*th=h;
// 1.判断pos是否合法
if (pos < 0) {
printf("删除的位置不合法\n");
return (datatype)-1;
}
// 2.通过循环找出删除节点的位置
while (h->next != th) {
if (pos != 0) {
pos--;
h = h->next;
} else {
// 4.找到了删除节点的位置,将节点删除即可。
tmp = h->next;
h->next = h->next->next;
data = tmp->data;
if (tmp != NULL) {
free(tmp);
tmp = NULL;
}
return data;
}
}
printf("删除的位置不合法\n");
return (datatype)-1;
}
单向循环链表的遍历
void LoopLinkShow(looplink_t* h)
{
looplink_t *th=h;
while (h->next != th) {
printf("-%d", h->next->data);
h = h->next;
}
printf("-\n");
}
单向循环链表的查询
datatype LoopLinkCheckDataByPos(looplink_t* h, int pos)
{
datatype data;
looplink_t* th = h;
// 1.判断pos是否合法
if (pos < 0) {
printf("查询的位置不合法\n");
return (datatype)-1;
}
// 2.通过循环找到查询的位置
while (h->next != th) {
if (pos != 0) {
pos--;
h = h->next;
} else {
// 查询到了位置
data = h->next->data;
return data;
}
}
printf("查询的位置不合法\n");
return (datatype)-1;
}
单向循环链表的更新
int LoopLinkUpdateDataByPos(looplink_t* h, int pos, datatype data)
{
looplink_t* th = h;
// 1.判断pos是否合法
if (pos < 0) {
printf("更新的位置不合法\n");
return -1;
}
// 2.通过循环找到更新的位置
while (h->next != th) {
if (pos != 0) {
pos--;
h = h->next;
} else {
// 更新数据
h->next->data = data;
return 0;
}
}
printf("更新的位置不合法\n");
return -1;
}
单向循环链表的整体代码
looplink.h
#ifndef __LOOPLINK_H__
#define __LOOPLINK_H__
#include <stdio.h>
#include <stdlib.h>
#define datatype int
typedef struct node {
datatype data;
struct node* next;
// 这个指针指向的是下一个节点,节点是结构体类型,所以指针也要定义成结构体指针
} looplink_t;
looplink_t* LoopLinkCreate(void);
int LoopLinkInsertHead(looplink_t *h,datatype data);
int LoopLinkInsertTail(looplink_t *h,datatype data);
int LoopLinkInsertPos(looplink_t *h,int pos,datatype data);
void LoopLinkShow(looplink_t *h);
datatype LoopLinkDeleteByPos(looplink_t *h,int pos);
datatype LoopLinkCheckDataByPos(looplink_t *h,int pos);
int LoopLinkUpdateDataByPos(looplink_t *h,int pos,datatype data);
#endif
looplink.c
#include "looplink.h"
looplink_t* LoopLinkCreate(void)
{
looplink_t* h;
h = (looplink_t*)malloc(sizeof(*h));
if (h == NULL) {
printf("malloc head memory error\n");
return NULL;
}
h->data = (datatype)0;
h->next = h;
return h;
}
int LoopLinkInsertHead(looplink_t* h, datatype data)
{
looplink_t* tmp;
tmp = (looplink_t*)malloc(sizeof(*tmp));
if (tmp == NULL) {
printf("malloc node memory error\n");
return -1;
}
tmp->data = data;
// 进行头插法
tmp->next = h->next;
h->next = tmp;
return 0;
}
int LoopLinkInsertTail(looplink_t* h, datatype data)
{
looplink_t* tmp;
looplink_t* th = h;
// 1.分配tmp节点,当data存入
tmp = (looplink_t*)malloc(sizeof(*tmp));
if (tmp == NULL) {
printf("malloc node memory error\n");
return -1;
}
tmp->data = data;
// 2.通过循环找到尾部节点
while (h->next != th) {
h = h->next;
}
// 3.将节点插入到当前位置
tmp->next = h->next;
h->next = tmp;
return 0;
}
int LoopLinkInsertPos(looplink_t* h, int pos, datatype data)
{
looplink_t *tmp, *th = h;
// 1.判断pos是否合法
if (pos < 0) {
printf("插入的位置不合法\n");
return -1;
}
// 2.通过循环找出插入节点的位置
while (h->next != th || pos == 0) {
if (pos != 0) {
pos--;
h = h->next;
} else {
// 3.找到了插入节点的位置,将节点插入即可。
tmp = (looplink_t*)malloc(sizeof(*tmp));
if (tmp == NULL) {
printf("malloc memory error\n");
return -1;
}
tmp->data = data;
tmp->next = h->next;
h->next = tmp;
return 0;
}
}
printf("插入的位置不合法\n");
return -1;
}
void LoopLinkShow(looplink_t* h)
{
looplink_t* th = h;
while (h->next != th) {
printf("-%d", h->next->data);
h = h->next;
}
printf("-\n");
}
datatype LoopLinkDeleteByPos(looplink_t* h, int pos)
{
datatype data;
looplink_t *tmp, *th = h;
// 1.判断pos是否合法
if (pos < 0) {
printf("删除的位置不合法\n");
return (datatype)-1;
}
// 2.通过循环找出删除节点的位置
while (h->next != th) {
if (pos != 0) {
pos--;
h = h->next;
} else {
// 4.找到了删除节点的位置,将节点删除即可。
tmp = h->next;
h->next = h->next->next;
data = tmp->data;
if (tmp != NULL) {
free(tmp);
tmp = NULL;
}
return data;
}
}
printf("删除的位置不合法\n");
return (datatype)-1;
}
datatype LoopLinkCheckDataByPos(looplink_t* h, int pos)
{
datatype data;
looplink_t* th = h;
// 1.判断pos是否合法
if (pos < 0) {
printf("查询的位置不合法\n");
return (datatype)-1;
}
// 2.通过循环找到查询的位置
while (h->next != th) {
if (pos != 0) {
pos--;
h = h->next;
} else {
// 查询到了位置
data = h->next->data;
return data;
}
}
printf("查询的位置不合法\n");
return (datatype)-1;
}
int LoopLinkUpdateDataByPos(looplink_t* h, int pos, datatype data)
{
looplink_t* th = h;
// 1.判断pos是否合法
if (pos < 0) {
printf("更新的位置不合法\n");
return -1;
}
// 2.通过循环找到更新的位置
while (h->next != th) {
if (pos != 0) {
pos--;
h = h->next;
} else {
// 更新数据
h->next->data = data;
return 0;
}
}
printf("更新的位置不合法\n");
return -1;
}
main.c
#include "looplink.h"
int main(int argc, char const* argv[])
{
looplink_t* h;
h = LoopLinkCreate();
if (h == NULL) {
printf("create loop link error\n");
return -1;
}
LoopLinkInsertHead(h, 40);
LoopLinkInsertHead(h, 30);
LoopLinkInsertHead(h, 20);
LoopLinkInsertHead(h, 10);
LoopLinkShow(h);
// LoopLinkInsertTail(h,50);
// LoopLinkShow(h);
// LoopLinkInsertPos(h,0,111);
// LoopLinkShow(h);
// printf("delete pos = %d\n", LoopLinkDeleteByPos(h, 3));
// printf("delete pos = %d\n", LoopLinkDeleteByPos(h, 0));
// printf("delete pos = %d\n", LoopLinkDeleteByPos(h, 0));
// printf("delete pos = %d\n", LoopLinkDeleteByPos(h, 0));
// printf("delete pos = %d\n", LoopLinkDeleteByPos(h, 0));
// LoopLinkShow(h);
printf("Check pos = %d\n", LoopLinkCheckDataByPos(h, 3));
LoopLinkUpdateDataByPos(h,4,444);
LoopLinkShow(h);
return 0;
}
单向循环链表的练习
void joseph(int n,int k,int m)
{
1.创建一个有头的单向循环链表
2.循环将1-n的数据插入到单向循环链表中
3.剪掉单向循环链表的头
4.按照上述的规则循环删除成员,直到循环链表中没有成员为止。
}
单向循环链表去头
looplink_t* LoopLinkCutHead(looplink_t* h)
{
looplink_t* th = h;
// 1.判空
if (h->next == th) {
printf("这个链表是空\n");
free(h);
return NULL;
}
// 2.通过循环找到最后一个节点
while (h->next != th) {
h = h->next;
}
// 3.让最后一个节点,指向头节点的下一个节点
h->next = th->next;
// 4.释放头节点的内存
if (th != NULL) {
free(th);
th = NULL;
}
// 5.返回
return h->next;
}
单向循环链表无头遍历
void LoopLinkNoHeadShow(looplink_t* h)
{
looplink_t* th = h;
while (h->next != th) {
printf("-%d", h->data);
h = h->next;
}
printf("-%d-\n", h->data);
}
约瑟夫环代码实现
void joseph(int n, int k, int m)
{
datatype data;
int pos = k + m - 2;
looplink_t* h;
// 1.创建一个有头的单向循环链表
h = LoopLinkCreate();
if (h == NULL) {
printf("create loop link error\n");
return;
}
// 2.循环将1-n的数据插入到单向循环链表中
for (int i = 0; i < n; i++) {
LoopLinkInsertHead(h, n - i);
}
LoopLinkShow(h);
// 3.剪掉单向循环链表的头
h = LoopLinkCutHead(h);
LoopLinkNoHeadShow(h);
// 4.按照上述的规则循环删除成员,直到循环链表中没有成员为止。
while(1){
if(pos > 1){
pos--;
h = h->next;
}else{
if((data = LoopLinkCheckDataByPos(h,0)) == (datatype)-1){
break;
}
printf("%d\t",data);
LoopLinkDeleteByPos(h,0);
pos = m;
}
}
printf("%d\n",h->data);
}