c语言josephus问题循环链表,循环单链表(C语言,无头节点,附约瑟夫杀人问题)...

实现以下操作

init 初始化

traverse 遍历

head_add 头追加(),尾追加(尾插法)只需要注释掉函数最后一行的头指针赋值

len 长度

insert 指定位置插入

search 正、反向查找数据,返回第1次匹配的位置,找不到返回-1

get 获取指定位置的数据

delete 删除指定位置的数据

clear 清空链表

(注:使用头节点实现更好操作一些)

代码

#include

#include

#include

typedef struct node {

int data;

struct node *pNext;

}NODE, *PNODE;

void init(PNODE *);

void traverse(PNODE);

void head_add(PNODE *, int);

int len(PNODE);

bool insert(PNODE *, int, int);

int search(PNODE, int, bool);

bool get(PNODE, int, int *);

bool delete(PNODE *, int, int *);

void clear(PNODE *);

void clear(PNODE *pHead)

{

printf("clear...");

PNODE q, head;

head = *pHead;

do {

q = *pHead;

*pHead = (*pHead)->pNext;

free(q);

} while (*pHead != head );

*pHead = NULL;

printf("success!\n");

}

bool delete(PNODE *pHead, int pos, int *pVal)

{

printf("尝试删除节点 %d ", pos);

PNODE p = *pHead, q;

int i = 1;

if (! p || pos < 1 || pos > len(p)) {

printf("失败\n");

return false;

}

if(pos == 1) {

while (p->pNext != *pHead) {

p = p->pNext;

}

// 保存节点1的数据

*pVal = (*pHead)->data;

// 尾节点指向头节点后面的节点

p->pNext = (*pHead)->pNext;

q = *pHead;

// 更新头指针

*pHead = p->pNext;

// 释放节点1

free(q);

}

else {

while (i < pos-1) {

p = p->pNext;

++i;

}

*pVal = p->pNext->data;

// 保存指向被删除节点的指针

q = p->pNext;

p->pNext = p->pNext->pNext;

free(q);

}

printf("成功, 值为 %d\n", *pVal);

return true;

}

bool get(PNODE head, int pos, int *pVal)

{

printf("尝试get %d ", pos);

PNODE p = head;

int i = 1;

if (! head || pos < 1 || pos > len(head)) {

printf("失败\n");

return false;

}

while (i < pos) {

p = p->pNext;

++i;

}

*pVal = p->data;

printf("成功, 值为 %d\n", *pVal);

return true;

}

int search(PNODE head, int val, bool forward)

{

PNODE p = head;

int i = 1, last = -1;

if (!head)

return -1;

if (forward) {

while (p->pNext != head && p->data != val) {

p = p->pNext;

++i;

}

if (p->data == val)

last = i;

}

else {

while (p->pNext != head) {

if (p->data == val) {

last = i;

}

p = p->pNext;

++i;

}

if (p->data == val)

last = i;

}

return last;

}

bool insert(PNODE *pHead, int pos, int val)

{

PNODE tmp, p;

int i = 1;

printf("尝试插入位置 %d 数值 %d: ", pos, val);

if (pos < 1 || pos > len(*pHead)+1) {

printf(" 无效的插入位置\n");

return false;

}

tmp = (PNODE)malloc(sizeof(NODE));

tmp->data = val;

if (! *pHead) {

*pHead = tmp;

tmp->pNext = *pHead;

printf(", 空链表的第1个节点");

}

else if (pos == 1) {

p = (*pHead)->pNext;

while (p->pNext != (*pHead)) {

p = p->pNext;

}

p->pNext = tmp;

tmp->pNext = *pHead;

// 更新头指针指向(不加下面这行则实现了尾插法)

*pHead = tmp;

}

else {

p = *pHead;

while (i < pos-1) {

p = p->pNext;

i++;

}

tmp->pNext = p->pNext;

p->pNext = tmp;

}

printf(", 成功\n");

return true;

}

int len(PNODE head)

{

PNODE p = head;

int i = 1;

if (!head)

return 0;

while (p->pNext != head) {

p = p->pNext;

++i;

}

return i;

}

void head_add(PNODE *pHead, int val)

{

printf("head_add node value: %d\n", val);

PNODE tmp, p;

if (*pHead == NULL) {

*pHead = (PNODE)malloc(sizeof(NODE));

if (! *pHead) {

printf("内存分配失败!\n");

return;

}

(*pHead)->data = val;

(*pHead)->pNext = *pHead;

}

else {

tmp = (PNODE)malloc(sizeof(NODE));

if (! tmp) {

printf("内存分配失败!\n");

return;

}

tmp->data = val;

p = (*pHead)->pNext;

while (p->pNext != (*pHead)) {

p = p->pNext;

}

p->pNext = tmp;

tmp->pNext = *pHead;

// 更新头指针指向(不加下面这行则实现了尾插法)

*pHead = tmp;

}

}

void traverse(PNODE head)

{

printf("遍历结果:\n");

PNODE p = head;

int i = 1;

if (! head) {

printf("链表为空!\n");

return;

}

do {

printf("第 %d 个节点, self %p, data %d, pNext %p\n", i, p, p->data, p->pNext);

p = p->pNext;

++i;

} while (p != head);

}

void init(PNODE *pHead)

{

PNODE tmp, p;

int val, i=1;

while (1) {

printf("请输入节点 %d 的值,结束初始化请输入负数: ", i);

scanf("%d", &val);

if (val < 0)

break;

if (*pHead == NULL) {

*pHead = (PNODE)malloc(sizeof(NODE));

if (! *pHead) {

printf("内存分配失败!\n");

return;

}

(*pHead)->data = val;

(*pHead)->pNext = *pHead;

printf("初始化头节点:self %p, data %d, pNext %p\n", *pHead, (*pHead)->data, (*pHead)->pNext);

}

else {

tmp = (PNODE)malloc(sizeof(NODE));

if (! tmp) {

printf("内存分配失败!\n");

return;

}

tmp->data = val;

tmp->pNext = *pHead;

p = (*pHead)->pNext;

while (p->pNext != (*pHead)) {

p = p->pNext;

}

p->pNext = tmp;

}

++i;

}

}

int main(void)

{

PNODE head;

int val;

traverse(head);

printf("len:%d\n", len(head));

init(&head);

traverse(head);

head_add(&head, 10);

head_add(&head, 9);

traverse(head);

printf("len:%d\n", len(head));

insert(&head, 1, 8);

insert(&head, 1, 6);

insert(&head, 2, 7);

traverse(head);

printf("len:%d\n", len(head));

insert(&head, 2, 11);

traverse(head);

printf("正向查找 5 所在节点:%d\n", search(head, 5, true));

printf("正向查找 11 所在节点:%d\n", search(head, 11, true));

printf("反向查找 11 所在节点:%d\n", search(head, 11, false));

printf("正向查找 13 所在节点:%d\n", search(head, 13, true));

printf("正向查找 133 所在节点:%d\n", search(head, 133, true));

printf("反向查找 133 所在节点:%d\n", search(head, 133, false));

// test get

get(head, 1, &val);

get(head, 5, &val);

get(head, 15, &val);

// test delete

delete(&head, 0, &val);

delete(&head, 1, &val);

traverse(head);

delete(&head, 1, &val);

traverse(head);

delete(&head, 2, &val);

traverse(head);

delete(&head, 3, &val);

traverse(head);

delete(&head, 100, &val);

clear(&head);

traverse(head);

return 0;

}

output

[root@8be225462e66 c]# gcc circular_linklist.c && ./a.out

遍历结果:

链表为空!

len:0

请输入节点 1 的值,结束初始化请输入负数: 11

初始化头节点:self 0x1dc7ac0, data 11, pNext 0x1dc7ac0

请输入节点 2 的值,结束初始化请输入负数: 12

请输入节点 3 的值,结束初始化请输入负数: 13

请输入节点 4 的值,结束初始化请输入负数: -1

遍历结果:

第 1 个节点, self 0x1dc7ac0, data 11, pNext 0x1dc7ae0

第 2 个节点, self 0x1dc7ae0, data 12, pNext 0x1dc7b00

第 3 个节点, self 0x1dc7b00, data 13, pNext 0x1dc7ac0

head_add node value: 10

head_add node value: 9

遍历结果:

第 1 个节点, self 0x1dc7b40, data 9, pNext 0x1dc7b20

第 2 个节点, self 0x1dc7b20, data 10, pNext 0x1dc7ac0

第 3 个节点, self 0x1dc7ac0, data 11, pNext 0x1dc7ae0

第 4 个节点, self 0x1dc7ae0, data 12, pNext 0x1dc7b00

第 5 个节点, self 0x1dc7b00, data 13, pNext 0x1dc7b40

len:5

尝试插入位置 1 数值 8: , 成功

尝试插入位置 1 数值 6: , 成功

尝试插入位置 2 数值 7: , 成功

遍历结果:

第 1 个节点, self 0x1dc7b80, data 6, pNext 0x1dc7ba0

第 2 个节点, self 0x1dc7ba0, data 7, pNext 0x1dc7b60

第 3 个节点, self 0x1dc7b60, data 8, pNext 0x1dc7b40

第 4 个节点, self 0x1dc7b40, data 9, pNext 0x1dc7b20

第 5 个节点, self 0x1dc7b20, data 10, pNext 0x1dc7ac0

第 6 个节点, self 0x1dc7ac0, data 11, pNext 0x1dc7ae0

第 7 个节点, self 0x1dc7ae0, data 12, pNext 0x1dc7b00

第 8 个节点, self 0x1dc7b00, data 13, pNext 0x1dc7b80

len:8

尝试插入位置 2 数值 11: , 成功

遍历结果:

第 1 个节点, self 0x1dc7b80, data 6, pNext 0x1dc7bc0

第 2 个节点, self 0x1dc7bc0, data 11, pNext 0x1dc7ba0

第 3 个节点, self 0x1dc7ba0, data 7, pNext 0x1dc7b60

第 4 个节点, self 0x1dc7b60, data 8, pNext 0x1dc7b40

第 5 个节点, self 0x1dc7b40, data 9, pNext 0x1dc7b20

第 6 个节点, self 0x1dc7b20, data 10, pNext 0x1dc7ac0

第 7 个节点, self 0x1dc7ac0, data 11, pNext 0x1dc7ae0

第 8 个节点, self 0x1dc7ae0, data 12, pNext 0x1dc7b00

第 9 个节点, self 0x1dc7b00, data 13, pNext 0x1dc7b80

正向查找 5 所在节点:-1

正向查找 11 所在节点:2

反向查找 11 所在节点:7

正向查找 13 所在节点:9

正向查找 133 所在节点:-1

反向查找 133 所在节点:-1

尝试get 1 成功, 值为 6

尝试get 5 成功, 值为 9

尝试get 15 失败

尝试删除节点 0 失败

尝试删除节点 1 成功, 值为 6

遍历结果:

第 1 个节点, self 0x1dc7bc0, data 11, pNext 0x1dc7ba0

第 2 个节点, self 0x1dc7ba0, data 7, pNext 0x1dc7b60

第 3 个节点, self 0x1dc7b60, data 8, pNext 0x1dc7b40

第 4 个节点, self 0x1dc7b40, data 9, pNext 0x1dc7b20

第 5 个节点, self 0x1dc7b20, data 10, pNext 0x1dc7ac0

第 6 个节点, self 0x1dc7ac0, data 11, pNext 0x1dc7ae0

第 7 个节点, self 0x1dc7ae0, data 12, pNext 0x1dc7b00

第 8 个节点, self 0x1dc7b00, data 13, pNext 0x1dc7bc0

尝试删除节点 1 成功, 值为 11

遍历结果:

第 1 个节点, self 0x1dc7ba0, data 7, pNext 0x1dc7b60

第 2 个节点, self 0x1dc7b60, data 8, pNext 0x1dc7b40

第 3 个节点, self 0x1dc7b40, data 9, pNext 0x1dc7b20

第 4 个节点, self 0x1dc7b20, data 10, pNext 0x1dc7ac0

第 5 个节点, self 0x1dc7ac0, data 11, pNext 0x1dc7ae0

第 6 个节点, self 0x1dc7ae0, data 12, pNext 0x1dc7b00

第 7 个节点, self 0x1dc7b00, data 13, pNext 0x1dc7ba0

尝试删除节点 2 成功, 值为 8

遍历结果:

第 1 个节点, self 0x1dc7ba0, data 7, pNext 0x1dc7b40

第 2 个节点, self 0x1dc7b40, data 9, pNext 0x1dc7b20

第 3 个节点, self 0x1dc7b20, data 10, pNext 0x1dc7ac0

第 4 个节点, self 0x1dc7ac0, data 11, pNext 0x1dc7ae0

第 5 个节点, self 0x1dc7ae0, data 12, pNext 0x1dc7b00

第 6 个节点, self 0x1dc7b00, data 13, pNext 0x1dc7ba0

尝试删除节点 3 成功, 值为 10

遍历结果:

第 1 个节点, self 0x1dc7ba0, data 7, pNext 0x1dc7b40

第 2 个节点, self 0x1dc7b40, data 9, pNext 0x1dc7ac0

第 3 个节点, self 0x1dc7ac0, data 11, pNext 0x1dc7ae0

第 4 个节点, self 0x1dc7ae0, data 12, pNext 0x1dc7b00

第 5 个节点, self 0x1dc7b00, data 13, pNext 0x1dc7ba0

尝试删除节点 100 失败

clear...success!

遍历结果:

链表为空!

[root@8be225462e66 c]#

约瑟夫杀人问题核心代码

注:其它函数使用上面的,最后结果为16,31

void kill(PNODE *);

void kill(PNODE *pHead)

{

int val;

PNODE p;

while (len(*pHead) >= 3) {

delete(pHead, 3, &val);

*pHead = (*pHead)->pNext->pNext;

}

}

output:

[root@8be225462e66 c]# gcc joseph.c && ./a.out

剩下的活人:

链表为空!

tail_add node value: 1

tail_add node value: 2

tail_add node value: 3

tail_add node value: 4

tail_add node value: 5

tail_add node value: 6

tail_add node value: 7

tail_add node value: 8

tail_add node value: 9

tail_add node value: 10

tail_add node value: 11

tail_add node value: 12

tail_add node value: 13

tail_add node value: 14

tail_add node value: 15

tail_add node value: 16

tail_add node value: 17

tail_add node value: 18

tail_add node value: 19

tail_add node value: 20

tail_add node value: 21

tail_add node value: 22

tail_add node value: 23

tail_add node value: 24

tail_add node value: 25

tail_add node value: 26

tail_add node value: 27

tail_add node value: 28

tail_add node value: 29

tail_add node value: 30

tail_add node value: 31

tail_add node value: 32

tail_add node value: 33

tail_add node value: 34

tail_add node value: 35

tail_add node value: 36

tail_add node value: 37

tail_add node value: 38

tail_add node value: 39

tail_add node value: 40

tail_add node value: 41

第 3 个人自杀, 编号为 3

第 3 个人自杀, 编号为 6

第 3 个人自杀, 编号为 9

第 3 个人自杀, 编号为 12

第 3 个人自杀, 编号为 15

第 3 个人自杀, 编号为 18

第 3 个人自杀, 编号为 21

第 3 个人自杀, 编号为 24

第 3 个人自杀, 编号为 27

第 3 个人自杀, 编号为 30

第 3 个人自杀, 编号为 33

第 3 个人自杀, 编号为 36

第 3 个人自杀, 编号为 39

第 3 个人自杀, 编号为 1

第 3 个人自杀, 编号为 5

第 3 个人自杀, 编号为 10

第 3 个人自杀, 编号为 14

第 3 个人自杀, 编号为 19

第 3 个人自杀, 编号为 23

第 3 个人自杀, 编号为 28

第 3 个人自杀, 编号为 32

第 3 个人自杀, 编号为 37

第 3 个人自杀, 编号为 41

第 3 个人自杀, 编号为 7

第 3 个人自杀, 编号为 13

第 3 个人自杀, 编号为 20

第 3 个人自杀, 编号为 26

第 3 个人自杀, 编号为 34

第 3 个人自杀, 编号为 40

第 3 个人自杀, 编号为 8

第 3 个人自杀, 编号为 17

第 3 个人自杀, 编号为 29

第 3 个人自杀, 编号为 38

第 3 个人自杀, 编号为 11

第 3 个人自杀, 编号为 25

第 3 个人自杀, 编号为 2

第 3 个人自杀, 编号为 22

第 3 个人自杀, 编号为 4

第 3 个人自杀, 编号为 35

剩下的活人:

编号为 16

编号为 31

[root@8be225462e66 c]

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值