Update README.md
优化叙述逻辑
This commit is contained in:
parent
2ae1f280b4
commit
391430df11
241
README.md
241
README.md
@ -1,22 +1,55 @@
|
|||||||
# 数据结构与算法练习代码
|
# 数据结构与算法练习代码
|
||||||
|
|
||||||
## 项目目标
|
## 项目目标
|
||||||
通过用C语言构建本学期所有数据结构和算法,来练编码.
|
本项目旨在通过C语言实现本学期所学的所有数据结构和算法,以提升编码能力、加深对数据结构和算法的理解,并培养良好的编程习惯。通过实际编写代码,我们将逐步构建一个完整的数据结构与算法库,为后续的软件开发和学习打下坚实的基础。
|
||||||
|
|
||||||
## 项目结构说明
|
## 项目结构说明
|
||||||
`main.c`由于测试和调用其它`.c`文件,其它算法源文件用其英文名命名,编写被调用文件时首先在`name.h`声名结构体和函数,然后在`name.c`实现功能.
|
项目采用模块化设计,每个数据结构或算法模块都独立封装,便于管理和复用。具体结构如下:
|
||||||
|
|
||||||
## 示例
|
- **`main.c`**:主程序文件,用于测试和调用其他模块的功能。它是整个项目的入口,通过它来运行和验证各个数据结构和算法模块的实现。
|
||||||
-[跳转到示例代码](#section2)
|
- **算法源文件**:每个数据结构或算法模块都有一个独立的源文件,文件名以其实现的功能的英文名命名,例如`linked_list.c`用于实现链表,`stack.c`用于实现栈等。这种命名方式直观且易于理解,方便开发者快速定位和使用相关模块。
|
||||||
|
- **头文件**:每个模块的头文件(如`linked_list.h`、`stack.h`等)用于声明该模块中定义的结构体和函数。头文件是模块对外的接口,它定义了模块可以被外部调用的函数和数据结构,隐藏了具体的实现细节,符合模块化设计的原则,同时也便于其他模块的引用和调用。
|
||||||
|
|
||||||
## 补充
|
在编写被调用模块的代码时,首先需要在对应的头文件中声明结构体和函数,明确模块的接口;然后在对应的源文件中实现这些函数的功能。这种分离接口和实现的方式,不仅有助于代码的组织和管理,还便于后续的维护和扩展。例如,如果需要修改某个模块的内部实现,只需修改其源文件,而无需修改头文件和主程序文件,只要保持接口不变,不会影响其他模块的正常调用。
|
||||||
### 知识补充
|
|
||||||
|
## 示例代码
|
||||||
|
以下是一个简单的示例,展示如何组织代码和实现功能。
|
||||||
|
|
||||||
|
### 简化示例代码
|
||||||
|
以下是一个简单的“Hello, World!”示例,展示如何在项目中添加一个新的模块。
|
||||||
|
|
||||||
|
#### `hello_world.h`
|
||||||
```c
|
```c
|
||||||
#ifndef LINKED_LIST_H
|
#ifndef HELLO_WORLD_H
|
||||||
#define LINKED_LIST_H
|
#define HELLO_WORLD_H
|
||||||
|
|
||||||
|
void print_hello_world();
|
||||||
|
|
||||||
|
#endif // HELLO_WORLD_H
|
||||||
#endif
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### `hello_world.c`
|
||||||
|
```c
|
||||||
|
#include "hello_world.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void print_hello_world() {
|
||||||
|
printf("Hello, World!\n");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 在`main.c`中调用
|
||||||
|
```c
|
||||||
|
#include "hello_world.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
print_hello_world();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 知识补充
|
||||||
|
### 头文件保护符
|
||||||
在C语言中,头文件(`.h`文件)通常使用预处理指令`#ifndef`、`#define`和`#endif`来防止头文件被重复包含,避免编译错误。这种技术被称为**头文件保护符**或**包含卫士**。
|
在C语言中,头文件(`.h`文件)通常使用预处理指令`#ifndef`、`#define`和`#endif`来防止头文件被重复包含,避免编译错误。这种技术被称为**头文件保护符**或**包含卫士**。
|
||||||
|
|
||||||
**工作原理:**
|
**工作原理:**
|
||||||
@ -34,143 +67,115 @@
|
|||||||
- **`#pragma once`指令**:一些编译器支持`#pragma once`,它可以防止头文件被多次包含,使用起来更简洁,但并非所有编译器都支持,使用`#ifndef`等预处理指令具有更好的可移植性。
|
- **`#pragma once`指令**:一些编译器支持`#pragma once`,它可以防止头文件被多次包含,使用起来更简洁,但并非所有编译器都支持,使用`#ifndef`等预处理指令具有更好的可移植性。
|
||||||
|
|
||||||
通过使用头文件保护符,可以有效防止头文件的重复包含,确保代码的正确编译。
|
通过使用头文件保护符,可以有效防止头文件的重复包含,确保代码的正确编译。
|
||||||
### 规则补充
|
|
||||||
统一使用`小写下划线命名法`
|
|
||||||
|
|
||||||
|
### 命名规范
|
||||||
|
为了保持代码的一致性和可读性,本项目统一使用**小写下划线命名法**。例如,变量名和函数名使用`variable_name`和`function_name`的形式,宏定义使用`MACRO_NAME`的形式。
|
||||||
|
|
||||||
|
## 如何参与项目
|
||||||
|
### 1. 克隆项目
|
||||||
|
#### 方式1:直接克隆
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/jdhnsu/C_DS_Algo.git
|
||||||
|
cd C_DS_Algo
|
||||||
|
```
|
||||||
|
#### 方式2(推荐):
|
||||||
|
使用`GitHub Desktop`客户端克隆项目,并在本地创建分支。
|
||||||
|
- [GitHub Desktop 下载](https://desktop.github.com/download/)
|
||||||
|
- [GitHub Desktop 汉化工具](https://github.com/robotze/GithubDesktopZhTool) (记得给项目点个赞!)
|
||||||
|
|
||||||
## 示例代码 <a id="section2"></a>
|
### 2. 添加新的数据结构或算法模块
|
||||||
|
- 创建一个新的头文件(如`new_module.h`)和源文件(如`new_module.c`)。
|
||||||
|
- 在头文件中声明结构体和函数接口。
|
||||||
|
- 在源文件中实现这些函数的功能。
|
||||||
|
- 在`main.c`中调用新模块的功能,验证其正确性。
|
||||||
|
|
||||||
`linked_list.h`:
|
### 3. 提交代码
|
||||||
|
- 提交你的代码到你的分支。
|
||||||
|
- 创建一个Pull Request,详细描述你的更改和新增功能。
|
||||||
|
|
||||||
|
### 4. 提出建议或问题
|
||||||
|
如果你有任何建议或遇到问题,欢迎在[Issues](https://github.com/jdhnsu/C_DS_Algo/issues)中提出。
|
||||||
|
|
||||||
|
## 示例:添加一个新的模块
|
||||||
|
假设我们要添加一个栈模块,以下是步骤:
|
||||||
|
|
||||||
|
1. **创建头文件`stack.h`**
|
||||||
```c
|
```c
|
||||||
#ifndef LINKED_LIST_H
|
#ifndef STACK_H
|
||||||
#define LINKED_LIST_H
|
#define STACK_H
|
||||||
|
|
||||||
#include <stdbool.h>
|
typedef struct Stack {
|
||||||
|
int* elements;
|
||||||
|
int capacity;
|
||||||
|
int top;
|
||||||
|
} Stack;
|
||||||
|
|
||||||
// 链表节点结构体
|
Stack* create_stack(int capacity);
|
||||||
typedef struct Node {
|
void push(Stack* stack, int element);
|
||||||
int data;
|
int pop(Stack* stack);
|
||||||
struct Node* next;
|
bool is_empty(Stack* stack);
|
||||||
} Node;
|
void free_stack(Stack* stack);
|
||||||
|
|
||||||
// 链表操作函数声明
|
|
||||||
Node* create_node(int data);
|
|
||||||
void append_node(Node** head, int data);
|
|
||||||
bool delete_node(Node** head, int data);
|
|
||||||
void print_list(const Node* head);
|
|
||||||
void free_list(Node** head);
|
|
||||||
|
|
||||||
#endif // LINKED_LIST_H
|
|
||||||
|
|
||||||
|
#endif // STACK_H
|
||||||
```
|
```
|
||||||
|
|
||||||
`linked_list.c`:
|
2. **创建源文件`stack.c`**
|
||||||
```c
|
```c
|
||||||
#include <stdio.h>
|
#include "stack.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "linked_list.h"
|
#include <stdio.h>
|
||||||
|
|
||||||
// 创建新节点
|
Stack* create_stack(int capacity) {
|
||||||
Node* create_node(int data) {
|
Stack* stack = (Stack*)malloc(sizeof(Stack));
|
||||||
Node* new_node = (Node*)malloc(sizeof(Node));
|
stack->elements = (int*)malloc(capacity * sizeof(int));
|
||||||
if (!new_node) {
|
stack->capacity = capacity;
|
||||||
fprintf(stderr, "内存分配失败\n");
|
stack->top = -1;
|
||||||
exit(EXIT_FAILURE);
|
return stack;
|
||||||
}
|
|
||||||
new_node->data = data;
|
|
||||||
new_node->next = NULL;
|
|
||||||
return new_node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 在链表末尾添加节点
|
void push(Stack* stack, int element) {
|
||||||
void append_node(Node** head, int data) {
|
if (stack->top == stack->capacity - 1) {
|
||||||
Node* new_node = create_node(data);
|
fprintf(stderr, "栈满,无法压入元素\n");
|
||||||
if (*head == NULL) {
|
|
||||||
*head = new_node;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Node* current = *head;
|
stack->elements[++stack->top] = element;
|
||||||
while (current->next != NULL) {
|
|
||||||
current = current->next;
|
|
||||||
}
|
|
||||||
current->next = new_node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除包含指定数据的节点
|
int pop(Stack* stack) {
|
||||||
bool delete_node(Node** head, int data) {
|
if (stack->top == -1) {
|
||||||
if (*head == NULL) {
|
fprintf(stderr, "栈空,无法弹出元素\n");
|
||||||
return false;
|
return -1;
|
||||||
}
|
}
|
||||||
Node* current = *head;
|
return stack->elements[stack->top--];
|
||||||
Node* previous = NULL;
|
|
||||||
|
|
||||||
// 查找要删除的节点
|
|
||||||
while (current != NULL && current->data != data) {
|
|
||||||
previous = current;
|
|
||||||
current = current->next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 未找到节点
|
bool is_empty(Stack* stack) {
|
||||||
if (current == NULL) {
|
return stack->top == -1;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除节点
|
void free_stack(Stack* stack) {
|
||||||
if (previous == NULL) {
|
free(stack->elements);
|
||||||
// 要删除的是头节点
|
free(stack);
|
||||||
*head = current->next;
|
|
||||||
} else {
|
|
||||||
previous->next = current->next;
|
|
||||||
}
|
}
|
||||||
free(current);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 打印链表
|
|
||||||
void print_list(const Node* head) {
|
|
||||||
const Node* current = head;
|
|
||||||
while (current != NULL) {
|
|
||||||
printf("%d -> ", current->data);
|
|
||||||
current = current->next;
|
|
||||||
}
|
|
||||||
printf("NULL\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 释放链表内存
|
|
||||||
void free_list(Node** head) {
|
|
||||||
Node* current = *head;
|
|
||||||
while (current != NULL) {
|
|
||||||
Node* next = current->next;
|
|
||||||
free(current);
|
|
||||||
current = next;
|
|
||||||
}
|
|
||||||
*head = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
```
|
||||||
`main.c`:
|
|
||||||
|
3. **在`main.c`中调用栈模块**
|
||||||
```c
|
```c
|
||||||
#include <stdio.h>
|
#include "stack.h"
|
||||||
#include "linked_list.h"
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
Node* head = NULL;
|
Stack* stack = create_stack(10);
|
||||||
insertNode(&head, 10);
|
push(stack, 10);
|
||||||
insertNode(&head, 20);
|
push(stack, 20);
|
||||||
insertNode(&head, 30);
|
printf("栈顶元素:%d\n", pop(stack));
|
||||||
printList(head);
|
free_stack(stack);
|
||||||
deleteNode(&head, 20);
|
|
||||||
printList(head);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
### 文件结构
|
|
||||||
```tree
|
4. **提交代码**
|
||||||
project/
|
- 提交你的`stack.h`和`stack.c`文件。
|
||||||
├── (忽略)
|
- 在`main.c`中验证栈模块的功能。(无需提交`main.c`文件)
|
||||||
├── README.md
|
- 提交时记得详细说明你的更改。
|
||||||
├── linked_list.h
|
|
||||||
├── linked_list.c
|
---
|
||||||
└── main.c
|
|
||||||
```
|
|
Loading…
x
Reference in New Issue
Block a user