实现以下操作
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]