自定義的雙端佇列deque
阿新 • • 發佈:2018-12-19
主要用於記錄一下(程式碼量太少,沒有使用git,又擔心程式碼丟失了),程式碼未必正確,請勿參考!
#ifndef MYDEQUEITERATOR_HPP_INCLUDED #define MYDEQUEITERATOR_HPP_INCLUDED #include<iostream> using namespace std; namespace com { namespace example { namespace stl { template<typename T> class MyDequeIterator { public: typedef T value_type; typedef T& reference; typedef const T& const_reference; typedef T* pointer; typedef const T* const_pointer; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef pointer* map_pointer; typedef MyDequeIterator self; #define BUFSIZE 32 public: /** * 獲取緩衝區的元素個數 * 當元素大小大於緩衝區時,該怎麼處理, * 還是有問題的 */ size_type get_element_count(){ size_type ele_size = sizeof(T); if(ele_size < BUFSIZE){ return BUFSIZE / ele_size; }else{ return 1; } } /** * 跳轉到控制中心的下一個node */ void goToNextNode(){ this->node += 1; this->start = *(this->node); this->end = this->start + get_element_count(); this->cur = this->start; } /** * 跳轉到控制中心的前一個node */ void goToPreviousNode(){ this->node -= 1; this->start = *(this->node); this->end = this->start + get_element_count(); this->cur = this->end - 1; } public: /** * 設定控制中心的node */ void setNode(map_pointer node){ this->node = node; this->start = *(this->node); this->end = this->start + get_element_count(); } public: /** * 前置++ */ self& operator++(){ if(this->cur >= this->end - 1){ goToNextNode(); }else{ this->cur++; } return *this; } /** * 後置++ */ self operator++(int){ self tmp = *this; ++(*this); return tmp; } /** * 前置-- */ self& operator--(){ if(this->cur <= this->start){ goToPreviousNode(); }else{ this->cur--; } return *this; } /** * 後置-- */ self operator--(int){ self tmp = *this; --(*this); return tmp; } reference operator*(){ return *(this->cur); } bool operator==(self& other){ return this->node == other.node && this->cur == other.cur; } bool operator!=(self& other){ return this->node != other.node || this->cur != other.cur; } /** * 最關鍵的一個方法,實現隨機訪問的功能 */ self& operator+=(difference_type diff){ size_type ele_count = get_element_count();//每個緩衝區的元素個數 difference_type offset = this->cur - this->start + diff;//相對某個特定緩衝區頭部的偏移 if(offset >= 0){ if(offset < ele_count){ this->cur += diff; }else{ size_type node_offset = offset / ele_count + 1; size_type end_offset = offset % ele_count; this->node += node_offset; setNode(this->node); this->cur = this->start + end_offset - 1;//設定指向緩衝區的當前位置 } }else{ size_type node_offset = -offset / ele_count + 1; size_type end_offset = -offset % ele_count; this->node -= node_offset; setNode(this->node); this->cur = this->end - end_offset;//設定指向緩衝區的當前位置 } return *this; } self operator+(difference_type diff){ self tmp = *this; tmp += diff; return tmp; } self& operator-=(difference_type diff){ return (*this) += (-diff); } self operator-(difference_type diff){ self tmp = *this; tmp -= diff; return tmp; } self& operator[](size_type index){ return *this += index; } public: map_pointer node;//指向控制中心的指標 pointer start;//指向某個緩衝區的開始 pointer end;//指向某個緩衝區的尾部 + 1 pointer cur;//指向某個緩衝區的當前位置 };//end MyDequeIterator }//end namespace stl }//end namespace example }//end namespace com #endif // MYDEQUEITERATOR_HPP_INCLUDED
#ifndef MYDEQUE_HPP_INCLUDED #define MYDEQUE_HPP_INCLUDED #include "com/example/stl/MyDequeIterator.hpp" #include <cstdlib> #include <new> namespace com { namespace example { namespace stl { template<typename T, typename Alloc = std::allocator<T>> class MyDeque{ public: typedef T value_type; typedef T& reference; typedef const T& const_reference; typedef T* pointer; typedef const T* const_pointer; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef pointer* map_pointer; typedef MyDequeIterator<T> iterator; typedef std::allocator<T> data_allocator_type; typedef std::allocator<pointer> control_allocator_type; #define BUFSIZE 32 private: /** * len指的是元素個數,BUFSIZE指的是緩衝區大小 */ MyDeque(size_type len){ this->len = len; size_type node_count = this->len * sizeof(value_type) / BUFSIZE + 1; this->control_len = 2 * node_count;//控制中心的大小是所需要的大小的2倍 //為控制中心分配空間 pcontrol = control_allocator.allocate(this->control_len * sizeof(pointer)); //給start迭代器和end迭代器設定初值 start.node = pcontrol + this->control_len / 4; end_1.node = start.node + node_count - 1; //start迭代器和end迭代器之間的緩衝區分配空間(注意這一塊邏輯的位置) size_type ele_count = start.get_element_count(); for(map_pointer p = start.node; p <= end_1.node; p++){ *p = data_allocator.allocate(sizeof(value_type) * ele_count); } //給start迭代器和end迭代器設定初值 start.setNode(start.node); end_1.setNode(end_1.node); start.cur = start.end; end_1.cur = end_1.start - 1;//注意這個地方的設定 } public: MyDeque(){ //MyDeque(0);//錯誤的,建構函式不能這樣呼叫 new(this) MyDeque(4); } private: /** * end迭代器是否到了控制中心的邊界了 */ bool is_end_boundary_control(){ return (end_1.node == (pcontrol + control_len - 1)) && (end_1.cur == (end_1.end - 1)); } /** * start迭代器是否到了控制中心的邊界了 */ bool is_start_boundary_control(){ return (start.node == pcontrol) && (start.cur == start.start); } /** * 給控制中心擴容 */ void expan_control(){ size_type tmp_len = this->control_len;//老的長度 map_pointer old_start_node = start.node;//老的start map_pointer old_end_node = end_1.node;//老的end map_pointer delete_point = this->pcontrol;//專門用於刪除的 size_type start_end_offset = end_1.node - start.node;//開始和結尾之間的偏移 this->control_len = this->control_len * 2; this->pcontrol = control_allocator.allocate(sizeof(pointer) * this->control_len); //將老的複製到新的裡面 size_type base_index = this->control_len / 4; map_pointer tmp_after_pointer = this->pcontrol + base_index; while(old_start_node <= old_end_node){ *tmp_after_pointer = *old_start_node; ++tmp_after_pointer; ++old_start_node; } //給迭代器重新賦值 start.node = this->pcontrol + base_index;//注意這個地方的計算 end_1.node = start.node + start_end_offset; //釋放老的控制中心所佔的空間 control_allocator.deallocate(delete_point, sizeof(pointer) * tmp_len); } /** * 在最後一位重新分配空間,然後插入元素 */ void allocate_and_insert_last(reference obj){ size_type ele_count = end_1.get_element_count(); *(++end_1.node) = data_allocator.allocate(sizeof(value_type) * ele_count); end_1.start = *(end_1.node); end_1.end = end_1.start + ele_count; end_1.cur = end_1.start; new(end_1.cur) value_type(obj);//呼叫copy建構函式 } /** * 在開始一位重新分配空間,然後插入元素 */ void allocate_and_insert_start(reference obj){ size_type ele_count = start.get_element_count(); *(--start.node) = data_allocator.allocate(sizeof(value_type) * ele_count); start.start = *(start.node); start.end = start.start + ele_count; start.cur = start.end - 1; new(start.cur) value_type(obj); } public: /** * 從後面插入一個元素 */ void push_back(reference obj){ if(is_end_boundary_control()){ //需要對控制中心擴容 expan_control(); allocate_and_insert_last(obj); }else{ ++(end_1.cur); if(end_1.cur < end_1.end){ new(end_1.cur) value_type(obj);//呼叫copy建構函式 }else{ allocate_and_insert_last(obj); } } this->len++;//長度增加 } /** * 彈出最後一個元素 */ value_type pop_back(){ value_type tmp = *(end_1.cur); --end_1; this->len--; return tmp; } /** * 返回最後一個元素,不彈出 */ reference back(){ return *(end_1.cur); } /** * 從容器的前面插入元素 */ void push_front(reference obj){ if(is_start_boundary_control()){ //需要擴容 expan_control(); allocate_and_insert_start(obj); }else{ --start.cur; if(start.cur < start.start){ allocate_and_insert_start(obj); }else{ new(start.cur) value_type(obj);//呼叫copy建構函式 } } this->len++; } /** * 從容器的前面彈出元素 */ value_type pop_front(){ value_type tmp = *(start.cur); ++start; this->len--; return tmp; } /** * 返回最前面的元素 */ reference front(){ return *(start.cur); } /** * 清空容器 */ void clear(){ map_pointer start_node = start.node; map_pointer end_node = end_1.node; size_type arr_len = end_node - start_node + 1; map_pointer* arr = new map_pointer[arr_len]; size_type ele_count = start.get_element_count(); //銷燬容器裡面的物件 for(int i = 0; i < arr_len; i++){ arr[i] = start_node + i; } for(int i = 0; i < arr_len; i++){ for(int j = 0; j < ele_count; j++){ data_allocator.destroy(*arr[i] + j); } data_allocator.deallocate(*arr[i], ele_count * sizeof(value_type)); } //銷燬控制中心 control_allocator.deallocate(this->pcontrol, sizeof(pointer) * this->control_len); delete[] arr; this->len = 0; new(this) MyDeque(0); } public: iterator begin(){ return this->start; } iterator end_my(){ return this->end_1; } size_type size(){ return this->len; } bool empty(){ return this->len == 0; } private: iterator start; iterator end_1; //指向控制中心的開始 //pcontrol + control_len就是控制中心的尾部 map_pointer pcontrol; size_type control_len;//控制中心的大小 size_type len; data_allocator_type data_allocator; control_allocator_type control_allocator; };//end MyDeque }//end namespace stl }//end namespace example }//end namespace com #endif // MYDEQUE_HPP_INCLUDED
// TestSTL.cpp : 定義控制檯應用程式的入口點。 // #include "stdafx.h" #include "com/example/stl/MyDeque.hpp" #include<iostream> using namespace com::example::stl; using namespace std; class Object{ public: Object(int x, float y){ this->x = x; this->y = y; } Object(){ } ~Object(){ //cout << "~Object 析構..." << endl; } public: int x; float y; public: void toString(){ cout << "x = " << x << ", " << "y = " << y << endl; } }; void test1(){ MyDeque<Object> dq; int len = 25; for(int i = 0; i < len; i++){ Object obj(i, i); dq.push_back(obj); } cout << "插入完成..........................." << endl; cout << endl; cout << "開始呼叫pop_back()..........................." << endl; //測試pop_back() for(int i = 0; i < len; i++){ dq.pop_back().toString(); } cout << "開始呼叫clear()..........................." << endl; dq.clear(); } void test2(){ MyDeque<Object> dq; int len = 25; for(int i = 0; i < len; i++){ Object obj(i, i); dq.push_front(obj); } //測試pop_front() for(int i = 0; i < len; i++){ dq.pop_front().toString(); } cout << "開始呼叫clear()..........................." << endl; dq.clear(); } void test3(){ MyDeque<int> dq; int len = 25; int tmp; for(int i = 0; i < len; i++){ tmp = i; dq.push_front(tmp); } //測試pop_front() for(int i = 0; i < len; i++){ cout << dq.pop_front() << endl; } dq.clear(); } void test4(){ MyDeque<float> dq; int len = 700; float tmp; for(int i = 0; i < len; i++){ tmp = i * 0.1f; dq.push_front(tmp); } //測試pop_front() for(int i = 0; i < len; i++){ cout << dq.pop_front() << endl; } } void test5(){ typedef MyDeque<Object>::iterator iterator_; MyDeque<Object> dq; int len = 800; for(int i = 0; i < len; i++){ Object obj(i, i); dq.push_back(obj); dq.push_front(obj); } //相等的時候也要打印出來 iterator_ it = dq.begin(); for(; it != dq.end_my(); ++it){ (*it).toString(); } (*it).toString(); } int main(int argc, _TCHAR* argv[]) { test5(); system("pause"); return 0; }