1. 程式人生 > >自定義的雙端佇列deque

自定義的雙端佇列deque

主要用於記錄一下(程式碼量太少,沒有使用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;
}