- vector容器实现
- 基础构造函数:
- n个元素的构造函数:
- vector拷贝构造函数:
- 析构函数:
- T at(int n)函数:
- void push_back(T val)函数:
- void pop_back()函数:
- void sort()函数:
- void clear()函数:
- int find(T val)函数:
- bool empty()函数:
- void printKVector()函数:
- size_t size()const函数:
- size_t capacity()const函数:
- void reserve(size_t n)函数:
- void insert(int n, T val)函数:
- void erase(int n)函数:
- iterator begin()const函数:
- iterator end()const函数:
- stack容器实现
- list容器实现
- map容器实现
- set容器实现
- deque容器实现
- queue容器实现
该次项目对所有的编程技能提升很大,虽然写的代码不是很完美,但是对我个人来说是能力上的巨大提升。
本工程的亮点的map和set全部基于链表实现,map是改造了双向循环链表,set是基于链表,但是在插入数据前进行重复性判断(我也参考csdn写了一个基于Rbtree版本,但是感觉不是自己的原创,就不放上来了,嘿嘿,给老师笔芯了 (´▽`ʃ♡ƪ))。
vector容器实现
vector底层采用数组实现,并初始化了三个指针:T m_begin; // 起始位置、T m_end; //结束位置、T* m_storagetail; //申请内存末尾
vector实现了以下函数
template<typename T>class KVector{public:KVector();KVector(int n, const T& val);KVector(const KVector<T>& other);~KVector();T at(int n);void push_back(T val);void pop_back();void sort();void clear();int find(T val);bool empty();void printKVector();size_t size()const;size_t capacity()const;void reserve(size_t n);void insert(int n, T val);void erase(int n);/*class iterator{public:bool operator!=(){return m_begin != m_end;}};*/typedef T* iterator;iterator begin()const;iterator end()const;private:T* m_begin; // 起始位置T* m_end; //结束位置T* m_storagetail; //申请内存末尾};
接下来分别讲解函数:
基础构造函数:
初始化三个指针,初始化vector底层数组(容量为0),三个指针的位置指向数组的头部。
template<typename T>KVector<T>::KVector(){m_begin = m_end = m_storagetail = nullptr;m_begin = new T[0];m_storagetail = m_end = m_begin;}
n个元素的构造函数:
初始化三个指针,初始化vector底层数组(容量为n),一层循环写入val,m_begin指针指向数组头部,m_storagetail 、m_end两个指针指向数组头部偏移n(当前数组尾部)。
template<typename T>KVector<T>::KVector(int n, const T& val){m_begin = m_end = m_storagetail = nullptr;m_begin = new T[n];for (int i = 0; i < n; i++){m_begin[i] = val;}m_storagetail = m_end = m_begin + n;}
vector拷贝构造函数:
初始化三个指针,计算拷贝vector的内存容量,并用两倍的该容量开辟新数组(提前开辟空间)。计算计算拷贝vector的元素个数,一层循环复制元素,m_begin指针指向数组头部,、m_end指针指向数组元素末尾,m_storagetail 指针指向数组内存容量末尾。
template<typename T>KVector<T>::KVector(const KVector<T>& other){m_begin = m_end = m_storagetail = nullptr;T temp = other.m_storagetail - other.m_begin;m_begin = new T[2 * temp];T n = other.m_end - other.m_begin;for (int i = 0; i < n; i++){m_begin[i] = other.m_begin[i];}m_end = m_begin + n;m_storagetail = m_begin + temp;}
析构函数:
调用clear()
template<typename T>KVector<T>::~KVector(){clear();}
T at(int n)函数:
查找函数,直接返回n位置元素。
template<typename T>T KVector<T>::at(int n){return this->m_begin[n];}
void push_back(T val)函数:
当元素末尾指针不等于内存末尾指针时,计算元素末尾位置,正常添加数据,偏移指针。
当元素末尾指针等于内存末尾指针时,先开辟2 * n + 1空间的内存,然后添加数据,偏移指针(因为初始时三个指针都是空指针,不加1,不能正常插入数据)。
template<typename T>void KVector<T>::push_back(T val){if (m_end != m_storagetail){T n = m_end - m_begin;m_begin[n] = val;m_end++;}else{size_t n = size();reserve(2 * n + 1);//当vector为null,需要加1;m_begin[n] = val;m_end++;}}
void pop_back()函数:
当vector内有数据时,最后一个数据清除,元素末尾指针向前偏移。
template<typename T>void KVector<T>::pop_back(){if (m_end - m_begin){m_begin[m_end - m_begin] = 0;m_end--;}}
void sort()函数:
简单两层循环的冒泡排序。
template<typename T>void KVector<T>::sort(){for (int i = 0; i < size(); i++){for (int j = 0; j < size() - 1; j++){if (m_begin[j] > m_begin[j + 1]){T temp = m_begin[j + 1];m_begin[j + 1] = m_begin[j];m_begin[j] = temp;}}}}
void clear()函数:
当vector内有数据时,删除底层数组,三个指针置空。
template<typename T>void KVector<T>::clear(){if (m_begin == nullptr){return;}delete[] m_begin;m_begin = m_end = m_storagetail = nullptr;}
int find(T val)函数:
循环遍历,找到返回位置,找不到返回-1。
template<typename T>int KVector<T>::find(T val){for (int i = 0; i < size(); i++){if (m_begin[i] == val){return i;}}return -1;}
bool empty()函数:
元素开始、末尾指针不相等。
template<typename T>bool KVector<T>::empty(){return (m_begin == m_end);}
void printKVector()函数:
计算元素个数,循环打印。
template<typename T>void KVector<T>::printKVector(){T n = this->m_end - this->m_begin;for (int i = 0; i < n; i++){std::cout << m_begin[i] << " ";}std::cout << std::endl;}
size_t size()const函数:
元素开始、末尾指针相减。
template <typename T>size_t KVector<T>::size()const{return m_end - m_begin;}
size_t capacity()const函数:
容量末尾指针与元素开始指针相减。
template <typename T>size_t KVector<T>::capacity()const{return m_storagetail - m_begin;}
void reserve(size_t n)函数:
如果开辟空间小于当前空间,忽略。开辟N容量的新数组,复制原数组到新数组,删除原数组,偏移三个指针。
void KVector<T>::reserve(size_t n){size_t oldsize = size();if(n <= capacity()){return;}else{T* newsize = new T[n];/*for (int i = 0; i < oldsize; i++){newsize[i] = m_begin[i];}*/memcpy(newsize, m_begin, sizeof(T) * size());delete[] m_begin;m_begin = newsize;m_end = m_begin + oldsize;m_storagetail = m_begin + n;}}
void insert(int n, T val)函数:
开辟一个新数组,复制n位置之前的元素,插入val,复制原数组n之后的数据,删除原数组,偏移三个指针。
template<typename T>void KVector<T>::insert(int n, T val){size_t oldsize = size();size_t oldcapacity = capacity();T* newsize = new T[oldcapacity * 2];for (int i = 0; i < n; i++){newsize[i] = m_begin[i];}newsize[n] = val;for (int j = n ; j < size() + 1; j++){newsize[j + 1] = m_begin[j];}delete[] m_begin;m_begin = newsize;m_end = m_begin + oldsize + 1;m_storagetail = m_begin + oldcapacity;
void erase(int n)函数:
n位置开始整体向前平移,元素末尾指针前移。
template<typename T>void KVector<T>::erase(int n){for (int i = n; i < size(); i++){m_begin[i] = m_begin[i + 1];}m_end--;}
iterator begin()const函数:
返回开始指针
template<typename T>typename KVector<T>::iterator KVector<T>::begin() const{return m_begin;}
iterator end()const函数:
返回元素末尾指针
template<typename T>typename KVector<T>::iterator KVector<T>::end() const{return m_end;}
stack容器实现
stack底层hevector一样采用数组实现,并初始化了三个指针:T m_begin; // 起始位置、T m_end; //结束位置、T* m_storagetail; //申请内存末尾
stack实现以下函数
template<typename T>class KStack{public:KStack();~KStack();bool empty();T peek();void pop();void push(T val);size_t search(T val);size_t size();void reserve(size_t n);typedef T* iterator;iterator begin()const;iterator end()const;private:T* m_begin; // 起始位置T* m_end; //结束位置T* m_storagetail; //申请内存末尾};
构造函数
初始化三个指针,初始化底层数组(容量为0),三个指针的位置指向数组的头部。
template<typename T>KStack<T>::KStack(){m_begin = m_end = m_storagetail = nullptr;m_begin = new T[0];m_storagetail = m_end = m_begin;}
析构函数
当stack内有数据时,删除底层数组,三个指针置空。
if (m_begin == nullptr){return;}delete[] m_begin;m_begin = m_end = m_storagetail = nullptr;
bool empty()函数
元素开始、末尾指针不相等。
template<typename T>bool KStack<T>::empty(){return (m_begin == m_end);}
T peek()函数
返回末尾最后一个元素。
template<typename T>T KStack<T>::peek(){return m_begin[m_end - m_begin - 1];}
void pop()函数
当stack内有数据时,最后一个数据清除,元素末尾指针向前偏移。
template<typename T>void KStack<T>::pop(){if (m_end - m_begin){m_begin[m_end - m_begin] = 0;m_end--;}}
void push(T val)函数
当元素末尾指针不等于内存末尾指针时,计算元素末尾位置,正常添加数据,偏移指针。
当元素末尾指针等于内存末尾指针时,先开辟2 * n + 1空间的内存,然后添加数据,偏移指针(因为初始时三个指针都是空指针,不加1,不能正常插入数据)。
template<typename T>void KStack<T>::push(T val){if (m_end != m_storagetail){T n = m_end - m_begin;m_begin[n] = val;m_end++;}else{size_t n = size();reserve(2 * n + 1);m_begin[n] = val;m_end++;}}
size_t search(T val)函数
遍历整个stack,找到返回位置,找不到返回-1。
template<typename T>size_t KStack<T>::search(T val){for (int i = 0; i < size(); i++){if (m_begin[i] == val){return size() - i;}}return -1;}
size_t size()函数
容量末尾指针与元素开始指针相减。
template<typename T>size_t KStack<T>::size(){return m_end - m_begin;}
void reserve(size_t n)函数
如果开辟空间小于当前空间,忽略。开辟N容量的新数组,复制原数组到新数组,删除原数组,偏移三个指针。
template<typename T>void KStack<T>::reserve(size_t n){size_t oldsize = size();if (n <= m_storagetail - m_begin){return;}else{T* newsize = new T[n];memcpy(newsize, m_begin, sizeof(T) * size());delete[] m_begin;m_begin = newsize;m_end = m_begin + oldsize;m_storagetail = m_begin + n;}}
iterator begin()const函数
返回开始指针
template<typename T>typename KStack<T>::iterator KStack<T>::begin()const{return m_begin;}
iterator end()const函数
返回元素末尾指针
template<typename T>typename KStack<T>::iterator KStack<T>::end()const{return m_end;}
list容器实现
采用双向循环链表实现,定义listnode
template<typename T>class KListNode{public:KListNode(T value, KListNode* prenode, KListNode* nextnode) :m_value(value), m_pre(prenode), m_next(nextnode){}T m_value;KListNode* m_pre;KListNode* m_next;};//双向链表
初始化KListNode
vector实现了如下函数
template <typename T>class KList{public:KList();~KList();void push_front(const T& val);void push_back(const T& val);void pop_front();void pop_back();void printList();bool empty();T back();T front();int size();void sort();int find(const T& val);T at(int n);/*typedef T* iterator;iterator begin() const;iterator end() const;*/private:KListNode<T>* m_head;KListNode<T>* m_tail;int m_size;};
构造函数
头节点指针,尾节点指针置空初始化。
template <typename T>KList<T>::KList(){m_head = nullptr;m_tail = nullptr;}
析构函数
头节点指针,尾节点指针置空并删除。
template <typename T>KList<T>::~KList(){m_head = nullptr;m_tail = nullptr;delete m_head;delete m_tail;}
void push_front(const T& val)函数
当list为空时:新建头节点,尾节点指向头节点,list的size加一;
当list不为空时:新建节点,新节点的下一个节点指向头节点,头结点的上一个节点指向新节点。新节点的上一个节点指向尾节点,尾节点的下一个结点指向新节点。头节点指针指向新节点,size加一。
template <typename T>void KList<T>::push_front(const T& val){if (m_head == nullptr){m_head = new KListNode<T>(val, nullptr, nullptr);m_tail = m_head;m_size++;}else{KListNode<T>* ptr = new KListNode<T>(val, nullptr, nullptr);ptr->m_next = this->m_head;ptr->m_pre = this->m_tail;m_tail->m_next = ptr;m_head->m_pre = ptr;this->m_head = ptr;m_size++;}}
void push_back(const T& val)函数
当list为空时:新建尾节点,头节点指向尾节点,list的size加一;
当list不为空时:新建节点,新节点的下一个节点指向头节点,头结点的上一个节点指向新节点。新节点的上一个节点指向尾节点,尾节点的下一个结点指向新节点。尾节点指针指向新节点,size加一。
template <typename T>void KList<T>::push_back(const T& val){if (m_tail == nullptr){m_tail = new KListNode<T>(val, nullptr, nullptr);m_head = m_tail;m_size++;}else{KListNode<T>* ptr = new KListNode<T>(val, nullptr, nullptr);ptr->m_next = m_head;m_head->m_pre = ptr;ptr->m_pre = m_tail;m_tail->m_next = ptr;m_tail = ptr;m_size++;}}
void pop_front()函数
尾节点的下一个节点指向头节点的下一个节点,头节点下一个节点的前一个节点指针指向尾节点。删除头节点,新的头节点指针指向尾节点下一个节点,size减一。
template <typename T>void KList<T>::pop_front(){m_tail->m_next = m_head->m_next;m_head->m_next->m_pre = m_tail;delete m_head;m_head = m_tail->m_next;m_size--;}
void pop_back()函数
头节点的前一个节点指向尾节点的前一个节点,尾节点的前一个节点的下一个节点指针指向头节点。删除头节点,尾节点指针指向头结点的上一个节点,size减一。
template <typename T>void KList<T>::pop_back(){m_head->m_pre = m_tail->m_pre;m_tail->m_pre->m_next = m_head;delete m_tail;m_tail = m_head->m_pre;m_size--;}
void printList()函数
新建ptr指针指向头节点,依据size,循环输出value。
template <typename T>void KList<T>::printList(){if (m_head){KListNode<T>* ptr = m_head;int count = 0;while (m_size != count){std::cout << ptr->m_value << " ";ptr = ptr->m_next;count++;}std::cout << std::endl;}else{return;}}
bool empty()函数
判断头节点是否等于尾节点
template <typename T>bool KList<T>::empty(){return (m_head == m_tail);}
T back()函数
返回尾节点的value
template <typename T>T KList<T>::back(){return this->m_tail->m_value;}
T front()函数
返回头节点的value
template <typename T>T KList<T>::front(){return this->m_head->m_value;}
int size()函数
返回m_size。
template <typename T>int KList<T>::size(){return this->m_size;}
void sort()函数
快排思想排序
template <typename T>void KList<T>::sort(){if (m_size > 1){int i = 1;int j = 0;KListNode<T>* ptr = m_head;while (m_size != i){j = 0;KListNode<T>* temp = ptr;while (j != m_size - i){if (ptr->m_value > temp->m_next->m_value){ptr->m_value += temp->m_next->m_value;temp->m_next->m_value = ptr->m_value - temp->m_next->m_value;ptr->m_value -= temp->m_next->m_value;}temp = temp->m_next;j++;}ptr = ptr->m_next;i++;}}}
int find(const T& val)函数
遍历list
template <typename T>int KList<T>::find(const T& val){KListNode<T>* ptr = m_head;for (int count = 0; count <= m_size; count++){if (ptr == nullptr){return -1;}if(ptr->m_value == val && ptr != nullptr){return count;}ptr = ptr->m_next;}return -1;}
T at(int n)函数
遍历list
template <typename T>T KList<T>::at(int n){if (n <= m_size){KListNode<T>* ptr = m_head;for (int i = 0; i < n; i++){ptr = ptr->m_next;}return ptr->m_value;}return -1;}
map容器实现
我的map使用了改造的双向循环链表(superlistnode),每个节点同时具有K类型的key和V类型的val。
template<typename K, typename V>class KSuperListNode{public:KSuperListNode(K key, V value, KSuperListNode* prenode, KSuperListNode* nextnode):m_key(key), m_value(value), m_pre(prenode), m_next(nextnode){}K m_key;V m_value;KSuperListNode* m_pre;KSuperListNode* m_next;};//改造双向链表
map容器实现了以下函数:
template<typename K, typename V>class KMap{public:KMap();~KMap();void insert(K key, V val);void printMap();int size();V at(K key);bool empty();void clear();void erase(K key);private:void sort();KSuperListNode<K, V>* m_head;KSuperListNode<K, V>* m_tail;int m_size = 0;};
初始化KSuperListNode
构造函数
初始化头指针,尾指针
template<typename K, typename V>KMap<K, V>::KMap(){m_head = nullptr;m_tail = nullptr;}
析构函数
调用clear()
template<typename K, typename V>KMap<K, V>::~KMap(){clear();}
void sort()私有函数
快排,依据key值进行大小排序,key值移动的同时,移动value值。
template<typename K, typename V>void KMap<K, V>::sort(){if (m_size > 1){int i = 1;int j = 0;KSuperListNode<K, V>* ptr = m_head;while (m_size != i){j = 0;KSuperListNode<K, V>* temp = ptr;while (j != m_size - i){if (ptr->m_key > temp->m_next->m_key){ptr->m_key += temp->m_next->m_key;ptr->m_value += temp->m_next->m_value;temp->m_next->m_key = ptr->m_key - temp->m_next->m_key;temp->m_next->m_value = ptr->m_value - temp->m_next->m_value;ptr->m_key -= temp->m_next->m_key;ptr->m_value -= temp->m_next->m_value;}temp = temp->m_next;j++;}ptr = ptr->m_next;i++;}}}
void insert(K key, V val)函数
当map为空时:新建节点,头节点、尾节点指向新节点,size加一。
当map不为空时:新建节点,新节点的下一个节点指向头节点,头节点的上一个节点指向新节点。尾节点的下一个节点指向新节点,新节点的上一个指针指向尾节点。size加一,整个map排序。
template<typename K, typename V>void KMap<K, V>::insert(K key, V val){if (m_tail == nullptr){m_tail = new KSuperListNode<K, V>(key, val, nullptr, nullptr);m_head = m_tail;m_size++;}else{KSuperListNode<K, V>* ptr = new KSuperListNode<K, V>(key, val, nullptr, nullptr);ptr->m_next = m_head;m_head->m_pre = ptr;ptr->m_pre = m_tail;m_tail->m_next = ptr;m_tail = ptr;m_size++;sort();}}
void printMap()函数
依据size遍历整个map
template<typename K, typename V>void KMap<K, V>::printMap(){if (m_head){KSuperListNode<K, V>* ptr = m_head;int count = 0;while (m_size != count){std::cout << "key: " << ptr->m_key << " value: " << ptr->m_value << std::endl;ptr = ptr->m_next;count++;}std::cout << std::endl;}else{return;}}
int size()函数
返回size
template<typename K, typename V>int KMap<K, V>::size(){return m_size;}
V at(K key)函数
遍历查找key,输出key对应的value。
template<typename K, typename V>V KMap<K, V>::at(K key){if (m_head){KSuperListNode<K, V>* ptr = m_head;int count = 0;while (m_size != count){if (ptr->m_key == key){return ptr->m_value;}ptr = ptr->m_next;count++;}}return 0;}
bool empty()函数
判断size
template<typename K, typename V>bool KMap<K, V>::empty(){if (m_size == 0){return true;}return false;}
void clear()函数
头尾指针置空并删除。
template<typename K, typename V>void KMap<K, V>::clear(){m_head = nullptr;m_tail = nullptr;delete m_head;delete m_tail;m_size = 0;}
void erase(K key)函数
遍历查询key,删除key位置的节点,连接key前后两个节点。
template<typename K, typename V>void KMap<K, V>::erase(K key){if (m_head){KSuperListNode<K, V>* ptr = m_head;int count = 0;while (m_size != count){if (ptr->m_key == key){KSuperListNode<K, V>* ptrnext = ptr->m_next;ptr->m_pre->m_next = ptrnext;ptrnext->m_pre = ptr->m_pre;delete ptr;m_size--;break;}ptr = ptr->m_next;count++;}}}
set容器实现
set容器基于我写的list容器实现。
set实现以下函数:
#include"klist.hpp"template<typename T>class KSet{public:KSet();~KSet();void insert(T value);void printSet();int find(T val);int size();private:KList<T> list;int m_size = 0;};
构造函数
template<typename T>KSet<T>::KSet(){KList<T> list;}
析构函数
template<typename T>KSet<T>::~KSet(){list.~KList();}
void insert(T value)函数
insert函数先判断set容器内是否含有该元素,若没有,插入该元素并排序。
template<typename T>void KSet<T>::insert(T value){if (list.size() >= 0){if (list.find(value) == -1){list.push_back(value);list.sort();}}}
void printSet()函数
template<typename T>void KSet<T>::printSet(){list.printList();}
int find(T val)函数
template<typename T>int KSet<T>::find(T val){return list.find(val);}
int size()函数
template<typename T>int KSet<T>::size(){return list.size();}
deque容器实现
deque容器基于我写的list容器实现。
deque实现了以下函数:
#include<iostream>#include"klist.hpp"template<typename T>class KDeque{public:KDeque();~KDeque();void push_back(T val);void push_front(T val);void pop_back();void pop_front();T front();T back();T at(int n);void ptintDEqueue();bool empty();int size();void sort();int find(const T& val);private:KList<T> list;};
构造函数
template<typename T>KDeque<T>::KDeque(){KList<T> list;}
析构函数
template<typename T>KDeque<T>::~KDeque(){list.~KList();}
void push_back(T val)函数
template<typename T>void KDeque<T>::push_back(T val){list.push_back(val);}
void push_front(T val)函数
template<typename T>void KDeque<T>::push_front(T val){list.push_front(val);}
void pop_back()函数
template<typename T>void KDeque<T>::pop_back(){list.pop_back();}
void pop_front()函数
template<typename T>void KDeque<T>::pop_front(){list.pop_front();}
T front()函数
emplate<typename T>T KDeque<T>::front(){return list.front();}
T back()函数
template<typename T>T KDeque<T>::back(){return list.back();}
T at(int n)函数
template<typename T>T KDeque<T>::at(int n){return list.at(n);}
void ptintDEqueue()函数
template<typename T>void KDeque<T>::ptintDEqueue(){list.printList();}
bool empty()函数
template<typename T>bool KDeque<T>::empty(){return list.empty();}
int size()函数
template<typename T>int KDeque<T>::size(){return list.size();}
void sort()函数
template<typename T>void KDeque<T>::sort(){list.sort();}
int find(const T& val)函数
template<typename T>int KDeque<T>::find(const T& val){return list.find(val);}
queue容器实现
queue容器基于我写的list容器实现。
queue实现了以下函数:
#include<iostream>#include"klist.hpp"template<typename T>class KQueue{public:KQueue();~KQueue();void push(T val);void pop();bool empty();T front();T back();int size();void printqueue();void sort();int find(const T& val);T at(int n);private:KList<T> list;};
构造函数
template<typename T>KQueue<T>::KQueue(){KList<T> list;}
析构函数
template<typename T>KQueue<T>::~KQueue(){list.~KList();}
void push(T val)函数
template<typename T>void KQueue<T>::push(T val){list.push_back(val);}
void pop()函数
template<typename T>void KQueue<T>::pop(){list.pop_front();}
bool empty()函数
bool KQueue<T>::empty(){return list.empty();}
T front()函数
template<typename T>T KQueue<T>::front(){return list.front();}
T back()函数
template<typename T>T KQueue<T>::back(){return list.back();}
int size()函数
template<typename T>int KQueue<T>::size(){return list.size();}
void printqueue()函数
template<typename T>void KQueue<T>::printqueue(){list.printList();}
void sort()函数
template<typename T>void KQueue<T>::sort(){list.sort();}
int find(const T& val)函数
template<typename T>int KQueue<T>::find(const T& val){return list.find(val);}
T at(int n)函数
template <typename T>T KQueue<T>::at(int n){return list.at(n);}
