mirror of
https://github.com/MeowLynxSea/ceditor.git
synced 2025-07-09 10:54:37 +00:00
Init mySTL
This commit is contained in:
parent
e918485724
commit
89b5045321
57
.vscode/settings.json
vendored
Normal file
57
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"*.lsp": "lua",
|
||||||
|
"deque": "cpp",
|
||||||
|
"array": "cpp",
|
||||||
|
"atomic": "cpp",
|
||||||
|
"bit": "cpp",
|
||||||
|
"*.tcc": "cpp",
|
||||||
|
"cctype": "cpp",
|
||||||
|
"charconv": "cpp",
|
||||||
|
"clocale": "cpp",
|
||||||
|
"cmath": "cpp",
|
||||||
|
"compare": "cpp",
|
||||||
|
"concepts": "cpp",
|
||||||
|
"cstddef": "cpp",
|
||||||
|
"cstdint": "cpp",
|
||||||
|
"cstdio": "cpp",
|
||||||
|
"cstdlib": "cpp",
|
||||||
|
"ctime": "cpp",
|
||||||
|
"cwchar": "cpp",
|
||||||
|
"cwctype": "cpp",
|
||||||
|
"string": "cpp",
|
||||||
|
"unordered_map": "cpp",
|
||||||
|
"vector": "cpp",
|
||||||
|
"exception": "cpp",
|
||||||
|
"algorithm": "cpp",
|
||||||
|
"functional": "cpp",
|
||||||
|
"iterator": "cpp",
|
||||||
|
"memory": "cpp",
|
||||||
|
"memory_resource": "cpp",
|
||||||
|
"numeric": "cpp",
|
||||||
|
"optional": "cpp",
|
||||||
|
"random": "cpp",
|
||||||
|
"string_view": "cpp",
|
||||||
|
"system_error": "cpp",
|
||||||
|
"tuple": "cpp",
|
||||||
|
"type_traits": "cpp",
|
||||||
|
"utility": "cpp",
|
||||||
|
"format": "cpp",
|
||||||
|
"initializer_list": "cpp",
|
||||||
|
"iosfwd": "cpp",
|
||||||
|
"iostream": "cpp",
|
||||||
|
"istream": "cpp",
|
||||||
|
"limits": "cpp",
|
||||||
|
"new": "cpp",
|
||||||
|
"numbers": "cpp",
|
||||||
|
"ostream": "cpp",
|
||||||
|
"span": "cpp",
|
||||||
|
"stdexcept": "cpp",
|
||||||
|
"streambuf": "cpp",
|
||||||
|
"text_encoding": "cpp",
|
||||||
|
"typeinfo": "cpp",
|
||||||
|
"variant": "cpp",
|
||||||
|
"cassert": "cpp"
|
||||||
|
},
|
||||||
|
"Codegeex.RepoIndex": true
|
||||||
|
}
|
28
.vscode/tasks.json
vendored
Normal file
28
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"type": "cppbuild",
|
||||||
|
"label": "C/C++: g++.exe 生成活动文件",
|
||||||
|
"command": "e:\\mingw64\\bin\\g++.exe",
|
||||||
|
"args": [
|
||||||
|
"-fdiagnostics-color=always",
|
||||||
|
"-g",
|
||||||
|
"${file}",
|
||||||
|
"-o",
|
||||||
|
"${fileDirname}\\${fileBasenameNoExtension}.exe"
|
||||||
|
],
|
||||||
|
"options": {
|
||||||
|
"cwd": "e:\\mingw64\\bin"
|
||||||
|
},
|
||||||
|
"problemMatcher": [
|
||||||
|
"$gcc"
|
||||||
|
],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"detail": "调试器生成的任务。"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": "2.0.0"
|
||||||
|
}
|
31
mySTL/container.h
Normal file
31
mySTL/container.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef CONTAINER_H
|
||||||
|
#define CONTAINER_H
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class Container {
|
||||||
|
public:
|
||||||
|
virtual ~Container() = default;
|
||||||
|
|
||||||
|
// 添加元素
|
||||||
|
virtual void push(const T& value) = 0;
|
||||||
|
|
||||||
|
// 移除元素
|
||||||
|
virtual void pop() = 0;
|
||||||
|
|
||||||
|
// 访问顶部元素
|
||||||
|
virtual T& top() = 0;
|
||||||
|
virtual const T& top() const = 0;
|
||||||
|
|
||||||
|
// 检查容器是否为空
|
||||||
|
virtual bool empty() const = 0;
|
||||||
|
|
||||||
|
// 返回容器中的元素数量
|
||||||
|
virtual size_t size() const = 0;
|
||||||
|
|
||||||
|
// 清空容器
|
||||||
|
virtual void clear() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CONTAINER_H
|
213
mySTL/my_deque.h
Normal file
213
mySTL/my_deque.h
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
#ifndef MY_DEQUE_H
|
||||||
|
#define MY_DEQUE_H
|
||||||
|
|
||||||
|
#include "container.h"
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class MyDeque : public Container<T> {
|
||||||
|
private:
|
||||||
|
static const size_t CHUNK_SIZE = 8; // 每个块的大小
|
||||||
|
|
||||||
|
T** map; // 中控器
|
||||||
|
size_t map_capacity; // 中控器容量
|
||||||
|
size_t start_chunk; // 起始块索引
|
||||||
|
size_t start_pos; // 起始块中的位置
|
||||||
|
size_t size_;
|
||||||
|
|
||||||
|
void initialize_map(size_t n) {
|
||||||
|
map_capacity = std::max(size_t(8), n / CHUNK_SIZE + 1);
|
||||||
|
map = new T*[map_capacity];
|
||||||
|
for (size_t i = 0; i < map_capacity; i++) {
|
||||||
|
map[i] = new T[CHUNK_SIZE];
|
||||||
|
}
|
||||||
|
start_chunk = map_capacity / 2;
|
||||||
|
start_pos = CHUNK_SIZE / 2;
|
||||||
|
size_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ensure_capacity(size_t needed_chunks) {
|
||||||
|
if (needed_chunks > map_capacity) {
|
||||||
|
size_t new_capacity = map_capacity * 2;
|
||||||
|
T** new_map = new T*[new_capacity];
|
||||||
|
|
||||||
|
size_t new_start = (new_capacity - needed_chunks) / 2;
|
||||||
|
for (size_t i = 0; i < map_capacity; i++) {
|
||||||
|
new_map[new_start + i] = map[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < new_start; i++) {
|
||||||
|
new_map[i] = new T[CHUNK_SIZE];
|
||||||
|
}
|
||||||
|
for (size_t i = new_start + map_capacity; i < new_capacity; i++) {
|
||||||
|
new_map[i] = new T[CHUNK_SIZE];
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] map;
|
||||||
|
map = new_map;
|
||||||
|
start_chunk = new_start;
|
||||||
|
map_capacity = new_capacity;
|
||||||
|
} else if (needed_chunks < map_capacity / 4 && needed_chunks >= 0) {
|
||||||
|
size_t new_capacity = map_capacity / 2;
|
||||||
|
T** new_map = new T*[new_capacity];
|
||||||
|
|
||||||
|
size_t new_start = (new_capacity - needed_chunks) / 2;
|
||||||
|
for (size_t i = 0; i < needed_chunks; i++) {
|
||||||
|
new_map[new_start + i] = map[start_chunk + i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t i = 0; i < new_start; i++) {
|
||||||
|
new_map[i] = new T[CHUNK_SIZE];
|
||||||
|
}
|
||||||
|
for (size_t i = new_start + needed_chunks; i < new_capacity; i++) {
|
||||||
|
new_map[i] = new T[CHUNK_SIZE];
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t i = 0; i < start_chunk; i++) {
|
||||||
|
delete[] map[i];
|
||||||
|
}
|
||||||
|
for(size_t i = start_chunk + needed_chunks; i < map_capacity; i++) {
|
||||||
|
delete[] map[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] map;
|
||||||
|
map = new_map;
|
||||||
|
start_chunk = new_start;
|
||||||
|
map_capacity = new_capacity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
MyDeque() {
|
||||||
|
initialize_map(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
~MyDeque() {
|
||||||
|
for (size_t i = 0; i < map_capacity; i++) {
|
||||||
|
delete[] map[i];
|
||||||
|
}
|
||||||
|
delete[] map;
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_back(const T& value) {
|
||||||
|
size_t end_chunk = (start_chunk + (start_pos + size_) / CHUNK_SIZE);
|
||||||
|
size_t end_pos = (start_pos + size_) % CHUNK_SIZE;
|
||||||
|
|
||||||
|
if (end_chunk >= map_capacity) {
|
||||||
|
ensure_capacity(end_chunk + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
map[end_chunk][end_pos] = value;
|
||||||
|
size_++;
|
||||||
|
}
|
||||||
|
|
||||||
|
T& back() {
|
||||||
|
if (empty()) {
|
||||||
|
throw std::out_of_range("back of empty deque");
|
||||||
|
}
|
||||||
|
size_t end_chunk = (start_chunk + (start_pos + size_ - 1) / CHUNK_SIZE);
|
||||||
|
size_t end_pos = (start_pos + size_ - 1) % CHUNK_SIZE;
|
||||||
|
return map[end_chunk][end_pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& back() const {
|
||||||
|
if (empty()) {
|
||||||
|
throw std::out_of_range("back of empty deque");
|
||||||
|
}
|
||||||
|
size_t end_chunk = (start_chunk + (start_pos + size_ - 1) / CHUNK_SIZE);
|
||||||
|
size_t end_pos = (start_pos + size_ - 1) % CHUNK_SIZE;
|
||||||
|
return map[end_chunk][end_pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
void pop_back() {
|
||||||
|
if (empty()) {
|
||||||
|
throw std::out_of_range("pop_back from empty deque");
|
||||||
|
}
|
||||||
|
size_--;
|
||||||
|
if((start_pos + size_ ) / CHUNK_SIZE + 1< map_capacity / 4) {
|
||||||
|
ensure_capacity((start_pos + size_) / CHUNK_SIZE + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_front(const T& value) {
|
||||||
|
if (start_pos == 0) {
|
||||||
|
if (start_chunk == 0) {
|
||||||
|
ensure_capacity(map_capacity + 1);
|
||||||
|
}
|
||||||
|
start_chunk--;
|
||||||
|
start_pos = CHUNK_SIZE;
|
||||||
|
}
|
||||||
|
start_pos--;
|
||||||
|
map[start_chunk][start_pos] = value;
|
||||||
|
size_++;
|
||||||
|
}
|
||||||
|
|
||||||
|
T& front() {
|
||||||
|
if (empty()) {
|
||||||
|
throw std::out_of_range("front of empty deque");
|
||||||
|
}
|
||||||
|
return map[start_chunk][start_pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& front() const {
|
||||||
|
if (empty()) {
|
||||||
|
throw std::out_of_range("front of empty deque");
|
||||||
|
}
|
||||||
|
return map[start_chunk][start_pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
void pop_front() {
|
||||||
|
if (empty()) {
|
||||||
|
throw std::out_of_range("pop_front from empty deque");
|
||||||
|
}
|
||||||
|
start_pos++;
|
||||||
|
if (start_pos == CHUNK_SIZE) {
|
||||||
|
start_chunk++;
|
||||||
|
start_pos = 0;
|
||||||
|
}
|
||||||
|
size_--;
|
||||||
|
if((start_pos + size_ ) / CHUNK_SIZE + 1< map_capacity / 4) {
|
||||||
|
ensure_capacity((start_pos + size_) / CHUNK_SIZE + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T& operator[](size_t n) {
|
||||||
|
size_t chunk = start_chunk + (start_pos + n) / CHUNK_SIZE;
|
||||||
|
size_t pos = (start_pos + n) % CHUNK_SIZE;
|
||||||
|
return map[chunk][pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
void push(const T& value) override {
|
||||||
|
push_front(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pop() override {
|
||||||
|
pop_front();
|
||||||
|
}
|
||||||
|
|
||||||
|
T& top() override {
|
||||||
|
return front();
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& top() const override {
|
||||||
|
return front();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const override {
|
||||||
|
return size_ == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const override {
|
||||||
|
return size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() override {
|
||||||
|
size_ = 0;
|
||||||
|
start_chunk = 0;
|
||||||
|
start_pos = 0;
|
||||||
|
ensure_capacity(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
43
mySTL/my_deque_test.cpp
Normal file
43
mySTL/my_deque_test.cpp
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#include "my_deque.h"
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
// 测试默认构造函数
|
||||||
|
MyDeque<int> dq;
|
||||||
|
assert(dq.empty());
|
||||||
|
assert(dq.size() == 0);
|
||||||
|
|
||||||
|
// 测试 push_back 和 back
|
||||||
|
dq.push_back(1);
|
||||||
|
assert(dq.back() == 1);
|
||||||
|
assert(dq.size() == 1);
|
||||||
|
|
||||||
|
// 测试 push_front 和 front
|
||||||
|
dq.push_front(2);
|
||||||
|
assert(dq.front() == 2);
|
||||||
|
assert(dq.size() == 2);
|
||||||
|
|
||||||
|
// 测试 pop_back
|
||||||
|
dq.pop_back();
|
||||||
|
assert(dq.front() == 2);
|
||||||
|
assert(dq.size() == 1);
|
||||||
|
|
||||||
|
// 测试 pop_front
|
||||||
|
dq.pop_front();
|
||||||
|
assert(dq.empty());
|
||||||
|
assert(dq.size() == 0);
|
||||||
|
|
||||||
|
// 测试 operator[]
|
||||||
|
dq.push_back(3);
|
||||||
|
dq.push_back(4);
|
||||||
|
assert(dq[0] == 3);
|
||||||
|
assert(dq[1] == 4);
|
||||||
|
|
||||||
|
// 测试 clear
|
||||||
|
dq.clear();
|
||||||
|
assert(dq.empty());
|
||||||
|
assert(dq.size() == 0);
|
||||||
|
|
||||||
|
printf("All tests passed!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
266
mySTL/my_list.h
Normal file
266
mySTL/my_list.h
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
#ifndef MY_LIST_H
|
||||||
|
#define MY_LIST_H
|
||||||
|
|
||||||
|
#include "container.h"
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class MyList : public Container<T> {
|
||||||
|
private:
|
||||||
|
struct Node {
|
||||||
|
T data;
|
||||||
|
Node* prev;
|
||||||
|
Node* next;
|
||||||
|
Node(const T& value, Node* p = nullptr, Node* n = nullptr)
|
||||||
|
: data(value), prev(p), next(n) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
Node* head; // 指向链表头部
|
||||||
|
Node* tail; // 指向链表尾部
|
||||||
|
size_t size_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MyList() : head(nullptr), tail(nullptr), size_(0) {}
|
||||||
|
|
||||||
|
~MyList() override {
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_back(const T& value) {
|
||||||
|
Node* new_node = new Node(value);
|
||||||
|
if (tail == nullptr) {
|
||||||
|
head = tail = new_node;
|
||||||
|
} else {
|
||||||
|
tail->next = new_node;
|
||||||
|
new_node->prev = tail;
|
||||||
|
tail = new_node;
|
||||||
|
}
|
||||||
|
size_++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_front(const T& value) {
|
||||||
|
Node* new_node = new Node(value, nullptr, head);
|
||||||
|
if (head == nullptr) {
|
||||||
|
head = tail = new_node;
|
||||||
|
} else {
|
||||||
|
head->prev = new_node;
|
||||||
|
head = new_node;
|
||||||
|
}
|
||||||
|
size_++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pop_back() {
|
||||||
|
if (empty()) {
|
||||||
|
throw std::out_of_range("pop from empty list");
|
||||||
|
}
|
||||||
|
Node* to_delete = tail;
|
||||||
|
tail = tail->prev;
|
||||||
|
if (tail) {
|
||||||
|
tail->next = nullptr;
|
||||||
|
} else {
|
||||||
|
head = nullptr;
|
||||||
|
}
|
||||||
|
delete to_delete;
|
||||||
|
size_--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pop_front() {
|
||||||
|
if (empty()) {
|
||||||
|
throw std::out_of_range("pop_front from empty list");
|
||||||
|
}
|
||||||
|
Node* to_delete = head;
|
||||||
|
head = head->next;
|
||||||
|
if (head) {
|
||||||
|
head->prev = nullptr;
|
||||||
|
} else {
|
||||||
|
tail = nullptr;
|
||||||
|
}
|
||||||
|
delete to_delete;
|
||||||
|
size_--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void insert(size_t index, const T& value) {
|
||||||
|
if (index > size_) {
|
||||||
|
throw std::out_of_range("index out of range");
|
||||||
|
}
|
||||||
|
if (index == 0) {
|
||||||
|
push_front(value);
|
||||||
|
} else if (index == size_) {
|
||||||
|
push_back(value);
|
||||||
|
} else {
|
||||||
|
Node* new_node = new Node(value);
|
||||||
|
Node* current = head;
|
||||||
|
for (size_t i = 0; i < index - 1; i++) {
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
new_node->prev = current;
|
||||||
|
new_node->next = current->next;
|
||||||
|
current->next->prev = new_node;
|
||||||
|
current->next = new_node;
|
||||||
|
size_++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void erase(size_t index) {
|
||||||
|
if (index >= size_) {
|
||||||
|
throw std::out_of_range("index out of range");
|
||||||
|
}
|
||||||
|
if (index == 0) {
|
||||||
|
pop_front();
|
||||||
|
} else if (index == size_ - 1) {
|
||||||
|
pop_back();
|
||||||
|
} else {
|
||||||
|
Node* to_delete = head;
|
||||||
|
for (size_t i = 0; i < index; i++) {
|
||||||
|
to_delete = to_delete->next;
|
||||||
|
}
|
||||||
|
to_delete->prev->next = to_delete->next;
|
||||||
|
if (to_delete->next) {
|
||||||
|
to_delete->next->prev = to_delete->prev;
|
||||||
|
}
|
||||||
|
delete to_delete;
|
||||||
|
size_--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T& back() {
|
||||||
|
if (empty()) {
|
||||||
|
throw std::out_of_range("top of empty list");
|
||||||
|
}
|
||||||
|
return tail->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& back() const {
|
||||||
|
if (empty()) {
|
||||||
|
throw std::out_of_range("top of empty list");
|
||||||
|
}
|
||||||
|
return tail->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
T& front() {
|
||||||
|
if (empty()) {
|
||||||
|
throw std::out_of_range("front of empty list");
|
||||||
|
}
|
||||||
|
return head->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& front() const {
|
||||||
|
if (empty()) {
|
||||||
|
throw std::out_of_range("front of empty list");
|
||||||
|
}
|
||||||
|
return head->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
class iterator {
|
||||||
|
private:
|
||||||
|
Node* node;
|
||||||
|
|
||||||
|
public:
|
||||||
|
iterator(Node* n = nullptr) : node(n) {}
|
||||||
|
|
||||||
|
iterator& operator++() { // 前缀++
|
||||||
|
if (node) node = node->next;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator operator++(int) { // 后缀++
|
||||||
|
iterator iterator = *this;
|
||||||
|
++(*this);
|
||||||
|
return iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator& operator--() { // 前缀--
|
||||||
|
if (node) node = node->prev;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator operator--(int) { // 后缀--
|
||||||
|
iterator iterator = *this;
|
||||||
|
--(*this);
|
||||||
|
return iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const iterator& other) const {
|
||||||
|
return node == other.node;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const iterator& other) const {
|
||||||
|
return node != other.node;
|
||||||
|
}
|
||||||
|
|
||||||
|
T& operator*() {
|
||||||
|
return node->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& operator*() const {
|
||||||
|
return node->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
T* operator->() {
|
||||||
|
return &(node->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
const T* operator->() const {
|
||||||
|
return &(node->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node * get_node() const {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 提供begin和end方法来返回迭代器
|
||||||
|
iterator begin() {
|
||||||
|
return iterator(head);
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator end() {
|
||||||
|
return iterator(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void erase(iterator ite) {
|
||||||
|
if (ite.get_node() == nullptr) {
|
||||||
|
throw std::out_of_range("index out of range");
|
||||||
|
}
|
||||||
|
Node* to_delete = ite.get_node();
|
||||||
|
to_delete->prev->next = to_delete->next;
|
||||||
|
if (to_delete->next) {
|
||||||
|
to_delete->next->prev = to_delete->prev;
|
||||||
|
}
|
||||||
|
delete to_delete;
|
||||||
|
size_--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void push(const T& value) override {
|
||||||
|
push_back(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pop() override {
|
||||||
|
pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
T& top() override {
|
||||||
|
return back();
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& top() const override {
|
||||||
|
return back();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const override {
|
||||||
|
return size_ == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const override {
|
||||||
|
return size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() override {
|
||||||
|
while(!empty()) {
|
||||||
|
pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
42
mySTL/my_list_test.cpp
Normal file
42
mySTL/my_list_test.cpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#include "my_deque.h"
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
// 测试默认构造函数
|
||||||
|
MyDeque<int> dq;
|
||||||
|
assert(dq.empty());
|
||||||
|
assert(dq.size() == 0);
|
||||||
|
|
||||||
|
// 测试 push_back 和 back
|
||||||
|
dq.push_back(1);
|
||||||
|
assert(dq.back() == 1);
|
||||||
|
assert(dq.size() == 1);
|
||||||
|
|
||||||
|
// 测试 push_front 和 front
|
||||||
|
dq.push_front(2);
|
||||||
|
assert(dq.front() == 2);
|
||||||
|
assert(dq.size() == 2);
|
||||||
|
|
||||||
|
// 测试 pop_back
|
||||||
|
dq.pop_back();
|
||||||
|
assert(dq.front() == 2);
|
||||||
|
assert(dq.size() == 1);
|
||||||
|
|
||||||
|
// 测试 pop_front
|
||||||
|
dq.pop_front();
|
||||||
|
assert(dq.empty());
|
||||||
|
assert(dq.size() == 0);
|
||||||
|
|
||||||
|
// 测试 operator[]
|
||||||
|
dq.push_back(3);
|
||||||
|
dq.push_back(4);
|
||||||
|
assert(dq[0] == 3);
|
||||||
|
assert(dq[1] == 4);
|
||||||
|
|
||||||
|
// 测试 clear
|
||||||
|
dq.clear();
|
||||||
|
assert(dq.empty());
|
||||||
|
assert(dq.size() == 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
148
mySTL/my_skiplist.h
Normal file
148
mySTL/my_skiplist.h
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <random>
|
||||||
|
#include "my_vector.h"
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
template<typename K, typename V>
|
||||||
|
class SkipList {
|
||||||
|
private:
|
||||||
|
struct Node {
|
||||||
|
K key;
|
||||||
|
V value;
|
||||||
|
std::vector<Node*> forward; // 存储每一层的前向指针
|
||||||
|
|
||||||
|
Node(K k, V v, int level)
|
||||||
|
: key(k), value(v), forward(level, nullptr) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
Node* head; // 头节点
|
||||||
|
int maxLevel; // 最大层数
|
||||||
|
int currentLevel; // 当前层数
|
||||||
|
float probability; // 生成上层节点的概率
|
||||||
|
|
||||||
|
// 生成随机层数
|
||||||
|
int randomLevel() {
|
||||||
|
int level = 1;
|
||||||
|
while ((float)rand()/RAND_MAX < probability && level < maxLevel) {
|
||||||
|
level++;
|
||||||
|
}
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
SkipList(int maxLvl = 16, float p = 0.5)
|
||||||
|
: maxLevel(maxLvl), probability(p), currentLevel(1) {
|
||||||
|
K minKey = std::numeric_limits<K>::min();
|
||||||
|
head = new Node(minKey, V(), maxLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void insert(K key, V value) {
|
||||||
|
MyVector<Node*> update(maxLevel, nullptr);
|
||||||
|
Node* current = head;
|
||||||
|
|
||||||
|
for (int i = currentLevel - 1; i >= 0; i--) {
|
||||||
|
while (current->forward[i] != nullptr &&
|
||||||
|
current->forward[i]->key < key) {
|
||||||
|
current = current->forward[i];
|
||||||
|
}
|
||||||
|
update[i] = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = current->forward[0];
|
||||||
|
|
||||||
|
if (current != nullptr && current->key == key) {
|
||||||
|
current->value = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int newLevel = randomLevel();
|
||||||
|
|
||||||
|
if (newLevel > currentLevel) {
|
||||||
|
for (int i = currentLevel; i < newLevel; i++) {
|
||||||
|
update[i] = head;
|
||||||
|
}
|
||||||
|
currentLevel = newLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* newNode = new Node(key, value, newLevel);
|
||||||
|
|
||||||
|
for (int i = 0; i < newLevel; i++) {
|
||||||
|
newNode->forward[i] = update[i]->forward[i];
|
||||||
|
update[i]->forward[i] = newNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool find(K key, V& value) {
|
||||||
|
Node* current = head;
|
||||||
|
|
||||||
|
for (int i = currentLevel - 1; i >= 0; i--) {
|
||||||
|
while (current->forward[i] != nullptr &&
|
||||||
|
current->forward[i]->key < key) {
|
||||||
|
current = current->forward[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
current = current->forward[0];
|
||||||
|
|
||||||
|
if (current != nullptr && current->key == key) {
|
||||||
|
value = current->value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool erase(K key) {
|
||||||
|
MyVector<Node*> update(maxLevel, nullptr);
|
||||||
|
Node* current = head;
|
||||||
|
|
||||||
|
for (int i = currentLevel - 1; i >= 0; i--) {
|
||||||
|
while (current->forward[i] != nullptr &&
|
||||||
|
current->forward[i]->key < key) {
|
||||||
|
current = current->forward[i];
|
||||||
|
}
|
||||||
|
update[i] = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = current->forward[0];
|
||||||
|
|
||||||
|
if (current == nullptr || current->key != key) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < currentLevel; i++) {
|
||||||
|
if (update[i]->forward[i] != current) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
update[i]->forward[i] = current->forward[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
delete current;
|
||||||
|
|
||||||
|
while (currentLevel > 1 && head->forward[currentLevel - 1] == nullptr) {
|
||||||
|
currentLevel--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void display() {
|
||||||
|
for (int i = currentLevel - 1; i >= 0; i--) {
|
||||||
|
Node* current = head->forward[i];
|
||||||
|
std::cout << "Level " << i << ": ";
|
||||||
|
while (current != nullptr) {
|
||||||
|
std::cout << current->key << ":" << current->value << " ";
|
||||||
|
current = current->forward[i];
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~SkipList() {
|
||||||
|
Node* current = head;
|
||||||
|
while (current != nullptr) {
|
||||||
|
Node* next = current->forward[0];
|
||||||
|
delete current;
|
||||||
|
current = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
33
mySTL/my_skiplist_test.cpp
Normal file
33
mySTL/my_skiplist_test.cpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#include "my_skiplist.h"
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
// 测试默认构造函数
|
||||||
|
SkipList<int, std::string> skipList;
|
||||||
|
|
||||||
|
// 测试 insert 和 find
|
||||||
|
skipList.insert(1, "one");
|
||||||
|
std::string value;
|
||||||
|
assert(skipList.find(1, value) && value == "one");
|
||||||
|
|
||||||
|
// 测试 erase
|
||||||
|
assert(skipList.erase(1));
|
||||||
|
assert(!skipList.find(1, value));
|
||||||
|
|
||||||
|
// 测试多个插入和查找
|
||||||
|
skipList.insert(2, "two");
|
||||||
|
skipList.insert(3, "three");
|
||||||
|
skipList.insert(4, "four");
|
||||||
|
assert(skipList.find(2, value) && value == "two");
|
||||||
|
assert(skipList.find(3, value) && value == "three");
|
||||||
|
assert(skipList.find(4, value) && value == "four");
|
||||||
|
|
||||||
|
// 测试 erase
|
||||||
|
assert(skipList.erase(3));
|
||||||
|
assert(!skipList.find(3, value));
|
||||||
|
|
||||||
|
// 测试 display (不进行断言,只是输出当前跳表结构)
|
||||||
|
// skipList.display();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
44
mySTL/my_stack.h
Normal file
44
mySTL/my_stack.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#ifndef MY_STACK_H
|
||||||
|
#define MY_STACK_H
|
||||||
|
|
||||||
|
#include "container.h"
|
||||||
|
#include "my_vector.h"
|
||||||
|
#include "my_deque.h"
|
||||||
|
#include "my_list.h"
|
||||||
|
|
||||||
|
//注意这里Container为模版参数,将具体的stack实现定义为MyVector
|
||||||
|
template <typename T, typename Container = MyDeque<T>>
|
||||||
|
class MyStack : public Container {
|
||||||
|
public:
|
||||||
|
void push(const T& value) {
|
||||||
|
Container::push(value); //用MyVector的push
|
||||||
|
}
|
||||||
|
|
||||||
|
void pop() {
|
||||||
|
if (!this->empty()) {
|
||||||
|
Container::pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T& top() {
|
||||||
|
return Container::top();
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& top() const {
|
||||||
|
return Container::top();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const {
|
||||||
|
return Container::empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const {
|
||||||
|
return Container::size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
Container::clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MY_STACK_H
|
38
mySTL/my_stack_test.cpp
Normal file
38
mySTL/my_stack_test.cpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#include "my_stack.h"
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
// 测试默认构造函数
|
||||||
|
MyStack<int> stack;
|
||||||
|
assert(stack.empty());
|
||||||
|
assert(stack.size() == 0);
|
||||||
|
|
||||||
|
// 测试 push 和 top
|
||||||
|
stack.push(1);
|
||||||
|
assert(stack.top() == 1);
|
||||||
|
assert(stack.size() == 1);
|
||||||
|
|
||||||
|
// 测试 push 和 pop
|
||||||
|
stack.push(2);
|
||||||
|
stack.pop();
|
||||||
|
assert(stack.top() == 1);
|
||||||
|
assert(stack.size() == 1);
|
||||||
|
|
||||||
|
// 测试 clear
|
||||||
|
stack.clear();
|
||||||
|
assert(stack.empty());
|
||||||
|
assert(stack.size() == 0);
|
||||||
|
|
||||||
|
// 测试多个 push 和 pop
|
||||||
|
stack.push(3);
|
||||||
|
stack.push(4);
|
||||||
|
stack.push(5);
|
||||||
|
assert(stack.top() == 5);
|
||||||
|
stack.pop();
|
||||||
|
assert(stack.top() == 4);
|
||||||
|
stack.pop();
|
||||||
|
assert(stack.top() == 3);
|
||||||
|
assert(stack.size() == 1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
168
mySTL/my_vector.h
Normal file
168
mySTL/my_vector.h
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
#ifndef MY_VECTOR_H
|
||||||
|
#define MY_VECTOR_H
|
||||||
|
|
||||||
|
#include "container.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class MyVector : public Container<T> {//继承
|
||||||
|
private:
|
||||||
|
T* m_data;
|
||||||
|
size_t m_size;
|
||||||
|
size_t m_capacity;
|
||||||
|
|
||||||
|
void reallocate(size_t new_capacity) {
|
||||||
|
T* new_data = new T[new_capacity];
|
||||||
|
size_t copy_size = std::min(m_size, new_capacity);
|
||||||
|
for (size_t i = 0; i < copy_size; ++i) {
|
||||||
|
new_data[i] = std::move(m_data[i]);
|
||||||
|
}
|
||||||
|
delete[] m_data;
|
||||||
|
m_data = new_data;
|
||||||
|
m_capacity = new_capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
MyVector() : m_data(nullptr), m_size(0), m_capacity(0) {}
|
||||||
|
|
||||||
|
explicit MyVector(size_t count, const T& value = T()) : m_size(count), m_capacity(count) {
|
||||||
|
m_data = new T[count];
|
||||||
|
std::fill_n(m_data, count, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
MyVector(const MyVector& other) : m_size(other.m_size), m_capacity(other.m_capacity) {
|
||||||
|
m_data = new T[m_capacity];
|
||||||
|
std::copy(other.m_data, other.m_data + m_size, m_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
MyVector(MyVector&& other) noexcept : m_data(other.m_data), m_size(other.m_size), m_capacity(other.m_capacity) {
|
||||||
|
other.m_data = nullptr;
|
||||||
|
other.m_size = other.m_capacity = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
~MyVector() override {
|
||||||
|
delete[] m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
MyVector& operator=(const MyVector& other) {
|
||||||
|
if (this != &other) {
|
||||||
|
MyVector tmp(other);
|
||||||
|
std::swap(m_data, tmp.m_data);
|
||||||
|
std::swap(m_size, tmp.m_size);
|
||||||
|
std::swap(m_capacity, tmp.m_capacity);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
MyVector& operator=(MyVector&& other) noexcept {
|
||||||
|
if (this != &other) {
|
||||||
|
delete[] m_data;
|
||||||
|
m_data = other.m_data;
|
||||||
|
m_size = other.m_size;
|
||||||
|
m_capacity = other.m_capacity;
|
||||||
|
other.m_data = nullptr;
|
||||||
|
other.m_size = other.m_capacity = 0;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void push(const T& value) override {
|
||||||
|
push_back(value); //具体函数的实现如下
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_back(const T& value) {
|
||||||
|
if (m_size == m_capacity) {
|
||||||
|
reallocate(m_capacity == 0 ? 1 : m_capacity * 2);
|
||||||
|
}
|
||||||
|
m_data[m_size++] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pop() override {
|
||||||
|
pop_back(); //具体函数的实现如下
|
||||||
|
}
|
||||||
|
|
||||||
|
void pop_back() {
|
||||||
|
if (!empty()) {
|
||||||
|
--m_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T& top() override {
|
||||||
|
return back();
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& top() const override {
|
||||||
|
return back();
|
||||||
|
}
|
||||||
|
|
||||||
|
T& back() {
|
||||||
|
if (empty()) {
|
||||||
|
throw std::out_of_range("Vector is empty");
|
||||||
|
}
|
||||||
|
return m_data[m_size - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& back() const {
|
||||||
|
if (empty()) {
|
||||||
|
throw std::out_of_range("Vector is empty");
|
||||||
|
}
|
||||||
|
return m_data[m_size - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const override {
|
||||||
|
return m_size == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const override {
|
||||||
|
return m_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t capacity() const {
|
||||||
|
return m_capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() override {
|
||||||
|
m_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reserve(size_t new_capacity) {
|
||||||
|
if (new_capacity > m_capacity) {
|
||||||
|
reallocate(new_capacity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize(size_t new_size, const T& value = T()) {
|
||||||
|
if (new_size > m_capacity) {
|
||||||
|
reallocate(new_size);
|
||||||
|
}
|
||||||
|
if (new_size > m_size) {
|
||||||
|
std::fill(m_data + m_size, m_data + new_size, value);
|
||||||
|
}
|
||||||
|
m_size = new_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
T& operator[](size_t index) {
|
||||||
|
return m_data[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& operator[](size_t index) const {
|
||||||
|
return m_data[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
T& at(size_t index) {
|
||||||
|
if (index >= m_size) {
|
||||||
|
throw std::out_of_range("Index out of range");
|
||||||
|
}
|
||||||
|
return m_data[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& at(size_t index) const {
|
||||||
|
if (index >= m_size) {
|
||||||
|
throw std::out_of_range("Index out of range");
|
||||||
|
}
|
||||||
|
return m_data[index];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MY_VECTOR_H
|
66
mySTL/my_vector_test.cpp
Normal file
66
mySTL/my_vector_test.cpp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#include "my_vector.h"
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
// 测试默认构造函数
|
||||||
|
MyVector<int> vec1;
|
||||||
|
assert(vec1.size() == 0);
|
||||||
|
assert(vec1.capacity() == 0);
|
||||||
|
|
||||||
|
// 测试带参数的构造函数
|
||||||
|
MyVector<int> vec2(5, 2);
|
||||||
|
assert(vec2.size() == 5);
|
||||||
|
assert(vec2.capacity() == 5);
|
||||||
|
for (size_t i = 0; i < vec2.size(); ++i) {
|
||||||
|
assert(vec2[i] == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试 push_back 和 size
|
||||||
|
vec1.push_back(1);
|
||||||
|
vec1.push_back(2);
|
||||||
|
vec1.push_back(3);
|
||||||
|
assert(vec1.size() == 3);
|
||||||
|
|
||||||
|
// 测试 pop_back 和 size
|
||||||
|
vec1.pop_back();
|
||||||
|
assert(vec1.size() == 2);
|
||||||
|
|
||||||
|
// 测试 back
|
||||||
|
assert(vec1.back() == 2);
|
||||||
|
|
||||||
|
// 测试 clear
|
||||||
|
vec1.clear();
|
||||||
|
assert(vec1.size() == 0);
|
||||||
|
|
||||||
|
// 测试 reserve
|
||||||
|
vec1.reserve(10);
|
||||||
|
assert(vec1.capacity() == 10);
|
||||||
|
|
||||||
|
// 测试 resize
|
||||||
|
vec1.resize(5, 3);
|
||||||
|
assert(vec1.size() == 5);
|
||||||
|
for (size_t i = 0; i < vec1.size(); ++i) {
|
||||||
|
assert(vec1[i] == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试 operator[]
|
||||||
|
vec1[0] = 4;
|
||||||
|
assert(vec1[0] == 4);
|
||||||
|
|
||||||
|
// 测试 at
|
||||||
|
assert(vec1.at(0) == 4);
|
||||||
|
|
||||||
|
// 测试 copy assignment
|
||||||
|
MyVector<int> vec3 = vec1;
|
||||||
|
assert(vec3.size() == vec1.size());
|
||||||
|
for (size_t i = 0; i < vec3.size(); ++i) {
|
||||||
|
assert(vec3[i] == vec1[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试 move assignment
|
||||||
|
MyVector<int> vec4 = std::move(vec3);
|
||||||
|
assert(vec4.size() == 5);
|
||||||
|
assert(vec3.size() == 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user