0%

04ds_04day

============================
2022-8-4
============================

note

1.写出有头单向循环链表的插入功能(头插 尾插)
2.实现冒泡法排序
    void sort(int *arr, int size);
有头单向循环链表的功能

无头单向不循环链表

约瑟夫环(约瑟夫杀人游戏)

--------------------------------------------
作业 :
1.把今天讲过的内容完完整整的复习一遍
2.把之前写过的5种链表都重新写一遍
    1)有头单向不循环链表
    2)有头单向循环链表
    3)无头单向不循环链表
    4)无头单向循环链表
    5)有头双向循环链表
--------------------------------------------

约瑟夫环(约瑟夫杀人游戏)

main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stdio.h>
#include "joseph.h"

int main(void)
{
JOSEPH *j = NULL;//j指针指向第一个有效结点
int player_num = 0;//保存玩家个数
int kill_num = 0;//数的数字
int alive = 0;//保存存活下来的人的ID

printf("Please Insert Player Number : ");
scanf("%d", &player_num);
j = joseph_insert(player_num);//插入数据结点
if(j == NULL)
return -1;
printf("===========================\n");
joseph_display(j);//遍历链表
printf("===========================\n");
printf("Please Insert Kill Number : ");
scanf("%d", &kill_num);
printf("***************************\n");
alive = joseph_play(j, player_num, kill_num);
printf("\n***************************\n");
printf("alive = %d\n", alive);

return 0;
}

joseph.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef __JOSEPH_H
#define __JOSEPH_H

typedef struct llist_node
{
int id;//编号
struct llist_node *next;
}JOSEPH;

JOSEPH *joseph_insert(int );

JOSEPH *joseph_display(JOSEPH *);

int joseph_play(JOSEPH *, int , int);

#endif

joseph.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <stdio.h>
#include <stdlib.h>
#include "joseph.h"

JOSEPH *joseph_insert(int player_num)
{
JOSEPH *j = NULL;//j指针指向第一个数据结点
JOSEPH *p = NULL;//p指针代替j指针进行移动
JOSEPH *newnode = NULL;//指针指向新创建的结点
int i = 1;//循环变量

j = malloc(sizeof(JOSEPH));
if(j == NULL)
return NULL;
j->id = i;
j->next = j;
p = j;

for(i = 2; i <= player_num; i++)
{
newnode = malloc(sizeof(JOSEPH));
if(newnode == NULL)
return j;
newnode->id = i;
newnode->next = p->next;
p->next = newnode;
p = p->next;
}

return j;
}

JOSEPH *joseph_display(JOSEPH *j)
{
JOSEPH *cur = NULL;

for(cur = j; cur->next != j; cur = cur->next)
printf("%d ", cur->id);
printf("%d\n", cur->id);
}

int joseph_play(JOSEPH *j, int player_num, int kill_num)
{
JOSEPH *back = j;
JOSEPH *cur = NULL;
int p_n = player_num;
int k_n = kill_num;
int alive = 0;

while(back->next != j)//为了找第一个结点的前一个位置
back = back->next;

while(--p_n)
{
for(k_n = kill_num - 1; k_n > 0; k_n--)
back = back->next;
cur = back->next;
back->next = cur->next;
printf("%d ", cur->id);
free(cur);
}
alive = back->id;
free(back);

return alive;
}

makefile

joseph : main.o joseph.o
    gcc -o $@ $^
clean :
    rm -rf *.o joseph

有头双向循环链表

/*
    有头双向循环链表
    1.创建头结点					llist_create();
    2.插入数据结点(头插法 尾插法)	llist_insert();
    3.遍历链表						llist_display();
    4.销毁链表						llist_destroy();
*/

main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <stdio.h>
#include "llist.h"

int main(void)
{
LLIST *handler = NULL;//指针指向链表的头结点
LLIST *find = NULL;//指针指向要查找的结点
LLIST data;//存储用户的数据
LLIST save;//保存取出的数据
int i = 0;//循环变量
int ret = 0;//接收函数的返回值
int find_id = 100;//要查找的ID号
char *find_name = "stu4";//要查找的名字

handler = llist_create();//创建头结点
if(handler == NULL)//判断头结点是否创建失败
return -1;//创建失败,结束程序,并且返回-1

for(i = 0; i < 5; i++)
{
data.id = 100 + i;//获取数据
sprintf(data.name, "stu%d", i);//获取数据
data.math = 100 - i;//获取数据
data.prev = data.next = NULL;//prev和next指向NULL
llist_insert(handler, &data, TAILINSERT);
//插入数据结点
}

llist_display(handler);//遍历链表

printf("====================\n");
/*
find = llist_find(handler, "stu9");//查找结点
if(find == NULL)//判断是否没有找到
printf("Not Find It!\n");
else
printf("Find It! %d %s %d\n",find->id, find->name,find->math);
*/
#if 0
ret = llist_delete(handler, &find_id);
if(ret != 0)
printf("Delete It Is Failed!\n");
else
printf("Delete It!\n");
#else
ret = llist_fetch(handler, find_name, &save);
if(ret != 0)
printf("Fetch It Is Failed!\n");
else
printf("Fetch It! %d %s %d\n",save.id, save.name, save.math);
#endif
printf("====================\n");

llist_display(handler);//遍历链表

llist_destroy(handler);//销毁链表

return 0;
}

llist.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#ifndef __LLIST_H
#define __LLIST_H

#define HEADINSERT 0//头插法
#define TAILINSERT 1//尾插法
#define NAMESIZE 20//字符数组的成员个数

typedef struct llist_node//链表中结点的结构体
{
int id;//数据域
char name[NAMESIZE];//数据域
int math;//数据域
struct llist_node *prev;//prev指针指向前一个结点
struct llist_node *next;//next指针指向后一个结点
}LLIST;

LLIST *llist_create();//创建头结点

int llist_insert(LLIST *, const void *, int );//插入数据

void llist_display(LLIST *);//遍历链表

void llist_destroy(LLIST *);//销毁链表

LLIST *llist_find(LLIST *, const void *);//查找结点

int llist_delete(LLIST *, const void *);//删除结点

int llist_fetch(LLIST *, const void *, void *);//取出结点

#endif

llist.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "llist.h"

LLIST *llist_create()
{
LLIST *handler = NULL;//指向头结点的指针

handler = malloc(sizeof(LLIST));//为头结点开辟空间
if(handler == NULL)//判断头结点空间是否开辟失败
return NULL;//开辟空间失败,结束函数,返回NULL

handler->prev = handler->next = handler;
//让头结点的前后指针都指向自己

return handler;//返回指向头结点的指针
}

int llist_insert(LLIST *handler,const void *data,int mode)
{
LLIST *p = handler;//代替handler指针进行移动
LLIST *newnode = NULL;//指向新创建的数据结点

newnode = malloc(sizeof(LLIST));//为数据结点开辟空间
if(newnode == NULL)//判断数据结点是否开辟失败
return -1;//开辟空间失败,结束函数,并且返回-1

memcpy(newnode, data, sizeof(LLIST));//拷贝数据

switch(mode)
{
case HEADINSERT : break;
case TAILINSERT : p = p->prev; break;
default : free(newnode); return -2;
}
newnode->next = p->next;
newnode->prev = p;
newnode->next->prev = newnode;
newnode->prev->next = newnode;
return 0;
}

void llist_display(LLIST *handler)
{
LLIST *cur = NULL;//指向每一个数据结点

for(cur = handler->next;cur!=handler;cur=cur->next)
printf("%d %s %d\n",cur->id,cur->name,cur->math);
}

void llist_destroy(LLIST *handler)
{
LLIST *cur = NULL;

for(cur=handler->next;cur!=handler;cur=handler->next)
{
cur->next->prev = cur->prev;
cur->prev->next = cur->next;
free(cur);//释放数据结点
}
free(cur);//释放头结点
}

LLIST *llist_find(LLIST *handler, const void *find_data)
{
LLIST *cur = NULL;

for(cur=handler->next;cur!=handler;cur=cur->next)
{
if(cur->id==*(int *)find_data ||
!(strcmp(cur->name, find_data)))
{
return cur;
}
}
return NULL;
}

int llist_delete(LLIST *handler, const void *find_data)
{
LLIST *cur = NULL;

cur = llist_find(handler, find_data);
if(cur == NULL)
return -1;

cur->prev->next = cur->next;
cur->next->prev = cur->prev;
free(cur);

return 0;
}

int llist_fetch(LLIST *handler, const void *find_data, void *save)
{
LLIST *cur = NULL;

cur = llist_find(handler, find_data);
if(cur == NULL)
return -1;

cur->prev->next = cur->next;
cur->next->prev = cur->prev;
memcpy(save, cur, sizeof(LLIST));
free(cur);

return 0;
}

makefile

1
2
3
4
llist : main.o llist.o
gcc -o $@ $^
clean :
rm -rf *.o llist