Compare commits

..

No commits in common. "9e270b7425300806192eeac58adb277af7792846" and "14d64cc0a276878ebf29f0917cae107621f94188" have entirely different histories.

4 changed files with 143 additions and 1154 deletions

View File

@ -36,23 +36,14 @@
## 性能比较
| 数据结构 | < | 时 |间 | | 复 | 杂 |度 | > | <空间复杂度> |
|---|---|---|---|---|---|---|---|---|---|
|---|(|**平**|**均**|) | (|**最**|**坏**| ) |**最坏**|
|---|访问|搜索|插入|删除|访问|搜索|插入|删除|---|
| 数组 | $O(1)$ | $O(n)$ | $O(n)$ | $O(n)$ | $O(1)$ | $O(n)$ | $O(n)$ | $O(n)$ | $O(n)$ |
| 栈 | $O(n)$ | $O(n)$ | $O(1)$ | $O(1)$ | $O(n)$ | $O(n)$ | $O(1)$ | $O(1)$ | $O(n)$ |
| 队列 | $O(n)$ | $O(n)$ | $O(1)$ | $O(1)$ | $O(n)$ | $O(n)$ | $O(1)$ | $O(1)$ | $O(n)$ |
| 单向链表 | $O(n)$ | $O(n)$ | $O(1)$ | $O(1)$ | $O(n)$ | $O(n)$ | $O(1)$ | $O(1)$ | $O(n)$ |
| 双向链表 | $O(n)$ | $O(n)$ | $O(1)$ | $O(1)$ | $O(n)$ | $O(n)$ | $O(1)$ | $O(1)$ | $O(n)$ |
| 跳表 | $O(log(n))$ | $O(log(n))$ | $O(log(n))$ | $O(log(n))$ | $O(n)$ | $O(n)$ | $O(n)$ | $O(n)$ | $O(n*log(n))$ |
| 哈希表 | $N/A$ | $O(1)$ | $O(1)$ | $O(1)$ | $N/A$ | $O(n)$ | $O(n)$ | $O(n)$ | $O(n)$
| 二叉搜索树 | $O(log(n))$ | $O(log(n))$ | $O(log(n))$ | $O(log(n))$ | $O(n)$ | $O(n)$ | $O(n)$ | $O(n)$ | $O(n)$ |
| AVL树 | $O(log(n))$ | $O(log(n))$ | $O(log(n))$ | $O(log(n))$ | $O(log(n))$ | $O(log(n))$ | $O(log(n))$ | $O(log(n))$ | $O(n)$ |
| 红黑树 | $O(log(n))$ | $O(log(n))$ | $O(log(n))$ | $O(log(n))$ | $O(log(n))$ | $O(log(n))$ | $O(log(n))$ | $O(log(n))$ | $O(n)$ |
| B树 | $O(log(n))$ | $O(log(n))$ | $O(log(n))$ | $O(log(n))$ | $O(log(n))$ | $O(log(n))$ | $O(log(n))$ | $O(log(n))$ | $O(n)$ |
|项目| 数组| 链表|
|---|---|---|
|查找| $O(1)$ | $O(n)$ |
|插入| $O(n)$ | $O(1)$ |
|删除| $O(n)$ | $O(1)$ |
**【A1】** 若链表的操作流程为,先查找元素再删除元素。那么时间复杂度确实是$O(n)$。但是链表的增删优势,在其他应用有体现。比如双向队列,插入和删除效率都为$O(1)$。
**【答疑】** 若链表的操作流程为,先查找元素再删除元素。那么时间复杂度确实是$O(n)$。但是链表的增删优势,在其他应用有体现。比如双向队列,插入和删除效率都为$O(1)$。
## 规范
### 版本说明

View File

@ -1,109 +1,62 @@
/**
* @file graph.h
* @author wenjf (Orig5826@163.com)
* @brief
* @brief
* @version 0.1
* @date 2024-09-03
*
*
* @copyright Copyright (c) 2024
*
*
*/
#ifndef _GRAPH_H
#define _GRAPH_H
#include "common.h"
#include "stack.h"
#include "queue.h"
enum _graph_type
{
GRAPH_UNDIRECTED,
GRAPH_DIRECTED,
// GRAPH_UNDIRECTED_WEIGHT,
// GRAPH_DIRECTED_WEIGHT,
struct _graph_node {
void *obj;
uint32_t **edge;
uint8_t *visited;
};
enum _graph_search
{
GRAPH_DFS,
GRAPH_BFS,
};
struct _graph_edge
{
uint32_t weight;
struct _graph_edge* next;
void *target;
};
struct _graph_node
{
void* obj;
struct _graph_node* next;
bool visited;
struct _graph_edge* edgehead;
};
struct _graph
{
// -------------------- private --------------------
struct _graph_node* _head;
struct _graph {
struct _graph_node *_head;
uint32_t **edges;
uint32_t _size;
uint32_t _obj_size;
uint32_t _capacity;
uint32_t _ratio;
enum _graph_type _type;
enum _graph_search _search;
// init
void (*init)(struct _graph *self);
bool (*from_matrix)(struct _graph *self, void *obj, uint32_t *edges, uint32_t size);
stack_t stack;
queue_t queue;
struct _iterator _iter;
void (*_destory)(struct _graph* self);
// -------------------- public --------------------
// kernel
// -> vertex
bool (*add_vertex)(struct _graph* self, void* obj);
bool (*del_vertex)(struct _graph* self, void* obj);
bool (*find_vertex)(struct _graph* self, void* obj);
// -> edge
bool (*add_edge)(struct _graph* self, void* from, void* to, uint32_t weight);
bool (*del_edge)(struct _graph* self, void* from, void* to);
bool (*find_edge)(struct _graph* self, void* from, void* to);
bool (*empty)(struct _graph* self);
bool (*full)(struct _graph* self);
bool (*add)(struct _graph *self, void *obj);
bool (*get)(struct _graph *self, uint32_t idx, void *obj);
bool (*remove)(struct _graph *self, uint32_t idx);
// base
uint32_t(*size)(struct _graph* self);
uint32_t(*capacity)(struct _graph* self);
bool (*clear)(struct _graph* self);
uint32_t (*size)(struct _graph *self);
uint32_t (*capacity)(struct _graph *self);
// iter
iterator_t (*iter)(struct _graph* self, enum _graph_search search, void *obj);
bool (*empty)(struct _graph *self);
bool (*full)(struct _graph *self);
// config
compare_fun_t compare; // !!! you have to implement this function
bool (*dfs)(struct _graph *self, uint32_t idx);
bool (*bfs)(struct _graph *self, uint32_t idx);
// others
bool (*from_matrix)(struct _graph* self, void* obj, uint32_t* edges, uint32_t size);
//
bool (*clear)(struct _graph *self);
void (*destory)(struct _graph *self);
// -------------------- debug --------------------
void (*print)(struct _graph* self);
void (*print_obj)(void* obj);
void (*print)(struct _graph *self);
void (*print_obj)(void *obj);
};
typedef struct _graph* graph_t;
graph_t graph_new(uint32_t obj_size);
// graph_t graph_new2(uint32_t obj_size, uint32_t capacity);
void graph_free(graph_t* graph);
graph_t graph_new2(uint32_t obj_size, uint32_t capacity);
void graph_free(graph_t *graph);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -12,171 +12,12 @@
void test_graph_new(void)
{
graph_t graph = graph_new(sizeof(int));
graph_t graph = graph_new2(sizeof(int), 10);
TEST_ASSERT_NOT_NULL(graph);
graph_free(&graph);
TEST_ASSERT_NULL(graph);
}
void test_graph_add_vertex(void)
{
const int size = 10;
int data[10] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
};
int temp = 11;
uint32_t i = 0;
graph_t graph = graph_new(sizeof(int));
TEST_ASSERT_NOT_NULL(graph);
graph->compare = compare_num;
graph->print_obj = print_num;
// test add_vertex
for(i = 0; i < size; i++)
{
TEST_ASSERT_TRUE(graph->add_vertex(graph, &data[i]));
}
// graph->print(graph);
// test find_vertex
TEST_ASSERT_TRUE(graph->find_vertex(graph, &data[0]));
TEST_ASSERT_TRUE(graph->find_vertex(graph, &data[9]));
TEST_ASSERT_FALSE(graph->find_vertex(graph, &temp));
// test del_vertex
TEST_ASSERT_TRUE(graph->del_vertex(graph, &data[0]));
TEST_ASSERT_FALSE(graph->find_vertex(graph, &data[0]));
// graph->print(graph);
for(i = 1; i < size; i++)
{
TEST_ASSERT_TRUE(graph->del_vertex(graph, &data[i]));
}
TEST_ASSERT_TRUE(graph->empty(graph));
// test clear
for(i = 0; i < size; i++)
{
TEST_ASSERT_TRUE(graph->add_vertex(graph, &data[i]));
}
// graph->print(graph);
graph->clear(graph);
// graph->print(graph);
TEST_ASSERT_TRUE(graph->empty(graph));
graph_free(&graph);
TEST_ASSERT_NULL(graph);
}
void test_graph_add_edge(void)
{
const int size = 10;
int data[10] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
};
int temp = 11;
uint32_t i = 0;
graph_t graph = graph_new(sizeof(int));
TEST_ASSERT_NOT_NULL(graph);
graph->compare = compare_num;
graph->print_obj = print_num;
// test add_vertex
for(i = 0; i < size; i++)
{
TEST_ASSERT_TRUE(graph->add_vertex(graph, &data[i]));
}
//graph->print(graph);
// test add_edge
TEST_ASSERT_TRUE(graph->add_edge(graph, &data[0], &data[1], 12));
TEST_ASSERT_TRUE(graph->add_edge(graph, &data[0], &data[2], 13));
TEST_ASSERT_TRUE(graph->add_edge(graph, &data[1], &data[3], 24));
TEST_ASSERT_TRUE(graph->add_edge(graph, &data[5], &data[6], 67));
TEST_ASSERT_FALSE(graph->add_edge(graph, &temp, &data[1], 0));
//graph->print(graph);
// test find_edge
TEST_ASSERT_TRUE(graph->find_edge(graph, &data[0], &data[1]));
TEST_ASSERT_TRUE(graph->find_edge(graph, &data[1], &data[3]));
// TEST_ASSERT_TRUE(graph->find_edge(graph, &data[6], &data[5])); // undirected graph
TEST_ASSERT_FALSE(graph->find_edge(graph, &data[4], &data[3]));
TEST_ASSERT_FALSE(graph->find_edge(graph, &data[0], &temp));
// test del_edge
TEST_ASSERT_TRUE(graph->del_edge(graph, &data[0], &data[1]));
//graph->print(graph);
TEST_ASSERT_FALSE(graph->find_edge(graph, &data[0], &data[1]));
TEST_ASSERT_TRUE(graph->del_edge(graph, &data[5], &data[6]));
//graph->print(graph);
graph_free(&graph);
TEST_ASSERT_NULL(graph);
}
void test_graph_iter(void)
{
const int size = 10;
int data[10] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
};
int temp = 11;
uint32_t i = 0;
graph_t graph = graph_new(sizeof(int));
TEST_ASSERT_NOT_NULL(graph);
graph->compare = compare_num;
graph->print_obj = print_num;
// test add_vertex
for(i = 0; i < size; i++)
{
TEST_ASSERT_TRUE(graph->add_vertex(graph, &data[i]));
}
// graph->print(graph);
// test add_edge
TEST_ASSERT_TRUE(graph->add_edge(graph, &data[0], &data[1], 12));
TEST_ASSERT_TRUE(graph->add_edge(graph, &data[0], &data[2], 13));
TEST_ASSERT_TRUE(graph->add_edge(graph, &data[1], &data[3], 24));
TEST_ASSERT_TRUE(graph->add_edge(graph, &data[5], &data[6], 67));
TEST_ASSERT_TRUE(graph->add_edge(graph, &data[7], &data[6], 87));
TEST_ASSERT_TRUE(graph->add_edge(graph, &data[8], &data[2], 92));
TEST_ASSERT_FALSE(graph->add_edge(graph, &temp, &data[1], 0));
graph->print(graph);
iterator_t iter_vertex = NULL;
iter_vertex = graph->iter(graph, GRAPH_BFS, &data[0]);
TEST_ASSERT_NOT_NULL(iter_vertex);
while(iter_vertex->hasnext(iter_vertex))
{
temp = *(int *)iter_vertex->next(iter_vertex);
graph->print_obj(&temp);
}
printf("\n");
iter_vertex = graph->iter(graph, GRAPH_DFS, &data[0]);
TEST_ASSERT_NOT_NULL(iter_vertex);
while(iter_vertex->hasnext(iter_vertex))
{
temp = *(int *)iter_vertex->next(iter_vertex);
graph->print_obj(&temp);
}
printf("\n");
graph_free(&graph);
TEST_ASSERT_NULL(graph);
}
#if 0
void test_graph_print(void)
{
graph_t graph = graph_new2(sizeof(int), 10);
@ -215,17 +56,12 @@ void test_graph_from_matrix(void)
graph_free(&graph);
TEST_ASSERT_NULL(graph);
}
#endif
void test_graph(void)
{
UnitySetTestFile(__FILE__);
RUN_TEST(test_graph_new);
RUN_TEST(test_graph_add_vertex);
RUN_TEST(test_graph_add_edge);
RUN_TEST(test_graph_iter);
// RUN_TEST(test_graph_print);
// RUN_TEST(test_graph_from_matrix);
}