04ds_08day

04ds_08day

============================
2022-8-10
============================

note

一.温故知新
    栈式的存储结构
        先进后出
    队列式的存储结构
        先进先出
    无论是顺序表还是链表都可以实现
    栈式
    struct node
    {
        int stack[6];
        int ind;
    };
    队列
    struct node
    {
        int queue[6];
        int front;
        int rear;
    };

    静态库和动态库
早测 
1.链表中倒数第k个结点
给定一个头结点为handler的单向不循环链表
输出该链表中倒数第k个结点
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
struct llist_node *func(struct llist_node *l, int k)
{
	struct llist_node *s = l;//慢指针
	struct llist_node *f = l;//快指针

	while(k--)
	{
		if(f == NULL)//判断链表是否提前结束
			return NULL;
		f = f->next;
	}
	while(f != NULL)
	{
		s = s->next;
		f = f->next;
	}
}
2.合并两个有序链表
将两个升序的无头单向不循环链表合并为一个新的升序链表并返回
新链表是通过拼接给定的两个链表的所有节点组成的
 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
struct llist_node *func(struct llist_node *l1, struct llist_node *l2)
{
	struct llist_node *l = NULL;//指向合并之后的链表
	struct llist_node *cur = NULL;

	if(l1 == NULL)
		return l2;
	if(l2 == NULL)
		return l1;
	if(l1->val < l2->val)
	{
		l = cur = l1;
		l1 = l1->next;
	}
	else
	{
		l = cur = l2;
		l2 = l2->next;
	}
	while(l1 != NULL && l2 != NULL)
	{
		if(l1->val < l2->val)
		{
			cur->next = l1;
			l1 = l1->next;
		}
		else
		{
			cur->next = l2;
			l2 = l2->next;
		}
		cur = cur->next;
	}
	if(l1 != NULL)
		cur->next = l1;
	if(l2 != NULL)
		cur->next = l2;

	return l;
}
3.简答题
给定一个有头单向不循环链表的头结点handler和要删除的结点p

内核链表

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
/usr/src/linux-hwe-5.4-headers-5.4.0-122/include/linux
list.h

struct list_head
{
	struct list_head *prev;
	struct list_head *next;
};

#define LIST_HEAD_INIT(name) { &(name), &(name) }

#define LIST_HEAD(name) \
    struct list_head name = LIST_HEAD_INIT(name)

LIST_HEAD(handler);
替换成
struct list_head handler = {&handler, &handler};

==============================
作业
1.把今天讲过的内容完完整整的复习一遍
2.把使用内核链表的功能补充完整
3.把早测的内容在电脑上写一遍
4.刷题
5.写项目
==============================

test.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
#include <stdio.h>
#include <stdlib.h>

struct list_head
{
	struct list_head *prev;
	struct list_head *next;
};

struct stu
{
	int id;
	char name[20];
	int math;
	struct list_head node;
};

int main(int argc, char *argv[])
{
	struct stu s;

	printf("&s = %p\n", &s);
	printf("&s.id = %p\n", &s.id);
	printf("s.name = %p\n", s.name);
	printf("&s.math = %p\n", &s.math);
	printf("&s.node = %p\n", &s.node);
	printf("SIZE=%ld\n", (size_t)&(((struct stu *)0)->node));

	return 0;
}
/*
	struct stu a = 0;//假如说a的地址是0x12345678
	struct stu *p = &a;//p 保存的地址是0x12345678

	p->node
	(size_t)&((struct stu *)(0)->node)
*/

kernellist

list.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
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
#ifndef _MYTEST_LIST_H
#define _MYTEST_LIST_H

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

#define container_of(ptr, type, member) ({			\
	const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
	(type *)( (char *)__mptr - offsetof(type,member) );})

struct list_head {
	struct list_head *prev;
	struct list_head *next;
};

#define LIST_HEAD_INIT(name) { &(name), &(name) }
//struct list_head name = {&name, &name};
#define LIST_HEAD(name) \
	struct list_head name = LIST_HEAD_INIT(name)

static inline void INIT_LIST_HEAD(struct list_head *list)
{
list->next = list;
	list->prev = list;
}
static inline void __list_add(struct list_head *new,
			      struct list_head *prev,
			      struct list_head *next)
{
	next->prev = new;
	new->next = next;
	new->prev = prev;
	prev->next = new;
}

static inline void list_add(struct list_head *new, struct list_head *head)
{
	__list_add(new, head, head->next);
}

static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
	__list_add(new, head->prev, head);
}

static inline void __list_del(struct list_head * prev, struct list_head * next)
{
	next->prev = prev;
	prev->next = next;
}

static inline void list_del(struct list_head *entry)
{
	__list_del(entry->prev, entry->next);
	entry->next = NULL;
	entry->prev = NULL;
}

#define list_entry(ptr, type, member) \
	container_of(ptr, type, member)

#define list_for_each(pos, head) \
	for (pos = (head)->next; pos != (head); pos = pos->next)

/*
	list_for_each(pos, head)
		遍历链表
		pos		指向每个数据节点的node
		head	指向头节点的指针
	list_entry(ptr, type, member)
		得到数据的首地址	
		ptr		node的地址
		type	客户的结构体名
		member	结构体中node的成员名
*/


#endif

kernellist.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
/*
	内核链表
		有头双向循环链表
		1.创建头结点
		2.插入数据结点(头插法 尾插法)
		3.遍历链表
		4.销毁链表
		==================
		5.查找结点
		6.删除结点
		7.拿出结点
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "list.h"

#define NAMESIZE 20

typedef struct stu
{
	int id;
	char name[NAMESIZE];
	int math;
	struct list_head node;
}STU;

void print(const void *data)
{
	const STU *p = data;
	printf("%d	%s	%d\n", p->id, p->name, p->math);
}

int id_cmp(const void *data, const void *key)
{
	const STU *p = data;
	const int *k = key;
	
	return !(p->id - *k);
}

int name_cmp(const void *data, const void *key)
{
	const STU *p = data;
	const char *k = key;
	return !(strcmp(p->name, k));
}

int main(void)
{
	LIST_HEAD(handler);//创建头结点
	STU *data = NULL;//将来指向开辟的空间,存储数据
	STU *datap = NULL;//将来指向数据结点的首地址
	struct list_head *pos = NULL;//pos指针指向每个数据结点
	int i = 0;//循环变量
	int find_id = 100;//要查找的ID号
	char *find_name = "stu4";//要查找的名字

	for(i = 0; i < 5; i++)
	{
		data = malloc(sizeof(STU));//开辟空间
		if(data == NULL)
			continue;
		data->id = 100 + i;
		sprintf(data->name, "stu%d", i);
		data->math = 100 - i;
		//list_add(&data->node, &handler);//头插法
		list_add_tail(&data->node, &handler);//尾插法
	}

	//不要加 ; 因为list_for_each是一个宏
	list_for_each(pos, &handler)//遍历链表
	{
		datap = list_entry(pos, STU, node);
		//获取数据结点的首地址
		print(datap);//打印数据
	}

	printf("----------------------\n");
	
	list_for_each(pos, &handler)//查找结点
	{
		datap = list_entry(pos, STU, node);
		if(name_cmp(datap, "stu9"))
		{
			printf("Find It!\n");
			print(datap);
		}
	}
	
	printf("----------------------\n");

	list_for_each(pos, &handler)//销毁链表
	{
		datap = list_entry(pos, STU, node);//找到首地址
		list_del(pos);//把数据结点从链表摘除
		free(datap);//释放空间
		pos = &handler;//指向头结点
	}

	return 0;
}