add: data-structure-lab & compiler-lab

This commit is contained in:
2024-10-30 17:23:52 +08:00
commit eb8c4fa451
35 changed files with 4266 additions and 0 deletions

3
maze/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
cmake-build-*/
build/
.idea/

10
maze/CMakeLists.txt Normal file
View File

@@ -0,0 +1,10 @@
cmake_minimum_required(VERSION 3.16)
project(maze)
set(CMAKE_CXX_STANDARD 11)
include_directories(${PROJECT_SOURCE_DIR}/include)
aux_source_directory(${PROJECT_SOURCE_DIR}/src SRCS)
add_executable(maze main.cpp ${SRCS})

71
maze/include/maze_node.h Normal file
View File

@@ -0,0 +1,71 @@
//
// Created by ricardo on 2022/10/25.
//
#ifndef MAZE_MAZE_NODE_H
#define MAZE_MAZE_NODE_H
// 全局的节点总数变量
// 虽然全局变量有点不好
extern int node_number;
struct maze_connect_node
{
// 连接的节点数组索引
int index;
struct maze_connect_node* next;
};
typedef struct maze_connect_node maze_connect_node_t;
typedef struct maze_connect_node* maze_connect_node_p;
struct maze_node
{
// 迷宫中结点的编号
int id;
// 与这个节点相连的节点链表
maze_connect_node_p connect_maze_nodes;
// 当前正在遍历的节点
maze_connect_node_p now_node;
};
// 迷宫节点结构体
typedef struct maze_node maze_node_t;
// 迷宫节点结构体指针
typedef struct maze_node* maze_node_p;
/**
* 创建迷宫节点数组
* @param num 迷宫中节点的数量
* @return 数组地址
*/
maze_node_p create_maze_node_array(int num);
/**
* 在指定的节点中添加与之相连的节点
* @param node 指定的节点引用
* @param target 与之相连的节点
* @return 是否添加成功
*/
bool maze_node_add_connect_node(maze_node_t& node, int target);
/**
* 读取迷宫配置文件
* @param filename 配置文件文件名
* @return 迷宫节点数组地址
*/
maze_node_p read_maze_file(char* filename);
/**
* 打印整个迷宫
* @param node_array 迷宫数组
*/
void print_maze(maze_node_p node_array);
/**
* 释放迷宫节点数组占据的空间
* @param node_array 迷宫节点数组引用
*/
void maze_node_free(maze_node_p& node_array);
#endif //MAZE_MAZE_NODE_H

83
maze/include/stack.h Normal file
View File

@@ -0,0 +1,83 @@
//
// Created by ricardo on 2022/10/25.
//
#ifndef MAZE_STACK_H
#define MAZE_STACK_H
#include "cstdlib"
#include "maze_node.h"
// 默认的栈大小
#define DEFAULT_STACK_LENGTH 200
// 由于将迷宫中的所有节点都储存在数组中
// 存储路径的栈就不用存储节点的指针
// 而是直接存储节点在数组中的索引
struct stack {
int* top;
int* base;
int stack_size;
};
typedef struct stack stack_t;
typedef struct stack* stack_p;
/**
* 初始化栈空间
* @param s 栈结构体的引用
* @return 栈是否创建成功
*/
bool init_stack(stack_t& s);
/**
* 判断栈是否为空
* @param s 对于栈结构体的引用
* @return
*/
bool stack_is_empty(const stack_t& s);
/**
* 判断栈是否已满
* @param s 对于结构体的引用
* @return
*/
bool stack_is_full(const stack_t& s);
/**
* 在栈中压入元素
* @param s 栈引用
* @param value 被压入栈的值
* @return 压入栈是否成功
*/
bool stack_push(stack_t& s, int index);
/**
* 在栈中弹出元素
* @param s 栈引用
* @param value 被弹出栈的值
* @return 弹出栈是否成功
*/
bool stack_pop(stack_t& s, int* index);
/**
* 获得栈底的元素
* @param s 栈引用
* @return
*/
int stack_get_bottom(const stack_t& s);
/**
* 获得栈顶的元素
* @param s 栈引用
* @return
*/
int stack_get_top(const stack_t& s);
/**
* 释放栈所占用的空间
* @param s 栈引用
*/
void stack_free(stack_t& s);
#endif //MAZE_STACK_H

76
maze/main.cpp Normal file
View File

@@ -0,0 +1,76 @@
#include "maze_node.h"
#include "stack.h"
#include "cstdio"
int main()
{
char config_file[10] = "maze.txt";
maze_node_p node_array = read_maze_file(config_file);
print_maze(node_array);
// 输入迷宫的开始和结束节点
int begin_node, end_node;
printf("Please enter the start node:\n");
scanf("%d", &begin_node);
printf("Please enter the end node:\n");
scanf("%d", &end_node);
// 初始化储存路径的栈
stack_t path_stack;
// 显然栈的最大大小就是迷宫中节点的数量
// 但是由于栈判满的原因需要多一个位置
path_stack.stack_size = node_number + 1;
init_stack(path_stack);
// 初始化将起点填入栈中
stack_push(path_stack, begin_node - 1);
while (stack_get_top(path_stack) + 1 != end_node)
{
maze_connect_node_p& node = node_array[stack_get_top(path_stack)].now_node;
if (node == nullptr)
{
// 节点已经遍历完不抱希望了
// 这个值仅占位
int temp;
stack_pop(path_stack, &temp);
continue;
}
// 遍历栈确定目标节点不在栈中
bool flag = false;
int* p = path_stack.base;
while (p != path_stack.top)
{
if (node->index == *p)
{
flag = true;
break;
}
p++;
}
if (!flag)
{
// 如果在栈中没发现这个节点
stack_push(path_stack, node->index);
}
// 将未探索的节点置为下一个
node = node->next;
}
// 打印路径栈
int* p = path_stack.base;
printf("%d", *p + 1);
p++;
while (p != path_stack.top)
{
printf("->%d", *p + 1);
p++;
}
printf("\n");
stack_free(path_stack);
maze_node_free(node_array);
return 0;
}

20
maze/maze.txt Normal file
View File

@@ -0,0 +1,20 @@
17
1-3
2-3
3-5
3-4
3-7
3-8
4-6
7-8
7-11
8-9
8-12
9-13
11-12
12-13
13-14
14-10
13-16
16-15
16-17

110
maze/src/maze_node.cpp Normal file
View File

@@ -0,0 +1,110 @@
#include "maze_node.h"
#include "cstdlib"
#include "cstdio"
int node_number;
maze_node_p create_maze_node_array(int num)
{
auto node = (maze_node_p) malloc(num * sizeof(maze_node_t));
maze_node_p p = node;
for (int i = 1; i <= num; ++i) {
p->id = i;
p->connect_maze_nodes = nullptr;
p++;
}
return node;
}
bool maze_node_add_connect_node(maze_node_t& node, int target)
{
auto new_node = (maze_connect_node_p) malloc(sizeof(maze_connect_node_t));
if (new_node == nullptr)
{
// 分配空间失败
return false;
}
new_node->next = nullptr;
new_node->index = target;
if (node.connect_maze_nodes == nullptr)
{
node.connect_maze_nodes = new_node;
// 遍历链表总是从头开始
node.now_node = new_node;
}
else
{
maze_connect_node_p connect_node = node.connect_maze_nodes;
while (connect_node->next != nullptr)
{
// 找到链表末节点
connect_node = connect_node->next;
}
connect_node->next = new_node;
}
return true;
}
maze_node_p read_maze_file(char* filename)
{
FILE* config_file;
char buffer[10];
config_file = fopen(filename, "r");
// 配置文件的第一行要求是迷宫中节点的总数
fgets(buffer, sizeof buffer, config_file);
char* point;
node_number = (int )strtol(buffer, &point, 10);
maze_node_p node_array = create_maze_node_array(node_number);
while (fgets(buffer, sizeof buffer, config_file) != nullptr)
{
int node1, node2;
sscanf(buffer, "%d-%d", &node1, &node2);
// 数组中的索引总是比编号小1
maze_node_add_connect_node(node_array[node1 - 1], node2 - 1);
maze_node_add_connect_node(node_array[node2 - 1], node1 - 1);
}
fclose(config_file);
return node_array;
}
void print_maze(maze_node_p node_array)
{
for (int i = 0; i < node_number; ++i) {
maze_node_t node = node_array[i];
maze_connect_node_p p = node.connect_maze_nodes;
while (p != nullptr)
{
printf("%d->%d\n", node.id, node_array[p->index].id);
p = p->next;
}
}
}
void maze_node_free(maze_node_p& node_array)
{
for(int i = 0; i < node_number; i++)
{
maze_connect_node_p node = node_array[i].connect_maze_nodes;
while (node != nullptr)
{
maze_connect_node_p temp = node;
node = node->next;
free(temp);
}
}
free(node_array);
node_array = nullptr;
}

81
maze/src/stack.cpp Normal file
View File

@@ -0,0 +1,81 @@
//
// Created by ricardo on 2022/10/25.
//
#include "stack.h"
bool init_stack(stack_t& s)
{
if (s.stack_size == 0)
{
// 如果没有设置栈的大小
// 就设置为默认大小
s.stack_size = DEFAULT_STACK_LENGTH;
}
auto p = (int* ) malloc(sizeof(int));
if (p == nullptr)
{
// 空间分配失败
return false;
}
s.base = p;
s.top = p;
return true;
}
bool stack_is_empty(const stack& s)
{
return s.base == s.top;
}
bool stack_is_full(const stack& s)
{
return s.base + s.stack_size == s.top;
}
bool stack_push(stack& s,int index)
{
if (stack_is_full(s))
{
// 栈已满
return false;
}
*s.top = index;
s.top++;
return true;
}
bool stack_pop(stack& s, int* index)
{
if (stack_is_empty(s))
{
// 栈为空
return false;
}
*index = *s.top;
s.top--;
return true;
}
int stack_get_bottom(const stack_t& s)
{
return *s.base;
}
int stack_get_top(const stack_t& s)
{
return *(s.top-1);
}
void stack_free(stack_t& s)
{
free(s.base);
s.base = nullptr;
s.top = nullptr;
s.stack_size = 0;
}