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