每日一题22:Deque与Trait

虽然之前写过一个Deque,但是那个属于C与C++混合的产品,近来在学习C++模板,所以写了一个C++版,同时第一次尝试使用Trait技术。

本来已经写好的文章,发表之后丢失了,好郁闷,没心情再写了,贴贴代码吧。

这个Trait是用来决定传递参数时是使用值传递还是引用传递

#ifndef _TYPE_TRAITS_H_
#define _TYPE_TRAITS_H_

namespace MyDataStructure
{
    template<typename T>
    class ParameterTrait
    {
    private:
        template<typename U>
        struct __ParaTrait
        {
            typedef U& ParameterType;
        };

        template<typename U>
        struct __ParaTrait<U*>
        {
            typedef U ParameterType;
        };

        template<typename U>
        struct __ParaTrait<U&>
        {
            typedef typename __ParaTrait<U>::ParameterType ParameterType;
        };

        template<>
        struct __ParaTrait<char>
        {
            typedef char ParameterType;
        };

        template<>
        struct __ParaTrait<unsigned char>
        {
            typedef unsigned char ParameterType;
        };

        template<>
        struct __ParaTrait<int>
        {
            typedef int ParameterType;
        };

        template<>
        struct __ParaTrait<unsigned int>
        {
            typedef unsigned int ParameterType;
        };

    public:
        typedef typename __ParaTrait<T>::ParameterType ParameterType;
    };
}

#endif

模板情况下实现的双端队列(其实这个只是双向链表,真正的双端队列比这个复杂太多了):

#ifndef _DEQUE_H_
#define _DEQUE_H_

#include "..\Utilites\type_traits.h"

namespace MyDataStructure
{
    template<typename T>
    class BiDirectionNode
    {
    private:
        typedef typename ParameterTrait<T>::ParameterType ParameterType;
    public:
        BiDirectionNode(const ParameterType value) : value(value),next(nullptr),pre(nullptr) {}
        BiDirectionNode(const BiDirectionNode& n)
        {
            _copy(n);
        }

        BiDirectionNode& operator = (const BiDirectionNode& n)
        {
            _copy(n);
            return *this;
        }
        T Value() const { return value; }
        T& Value() { return value; }
        T* Next() { return next; }
    public:
        void _copy(const BiDirectionNode& n)
        {
            value = n.value;
            next = n.next;
            pre = n.pre;
        }
        T value;
        BiDirectionNode* pre;
        BiDirectionNode* next;
    };

    template<typename T>
    class Deque
    {
    private:
        typedef typename BiDirectionNode<T> NodeType;
        typedef typename ParameterTrait<T>::ParameterType ParameterType;
    public:
        Deque() : size(0), head(nullptr),tail(nullptr){}
        Deque(const Deque& d){ _copy(d); }
        Deque& operator=(const Deque& d){ _destroy(); _copy(d); return *this; }
        ~Deque(){ _destroy(); }
        void Clear() { _destroy(); }
        const int Size() { return size; }
        bool Empty(){ return size == 0; }
        void Push(const ParameterType value)
        {
            NodeType* n = new NodeType(value);
            _push(n);
        }
        void Insert(const ParameterType value)
        {
            NodeType* n = new NodeType(value);
            _insert(n);
        }
        bool Pop(T& value)
        {
            if (size == 0)
                return false;
            value = head->value;
            NodeType* p = head;
            if (size == 1)
            {
                head = tail = nullptr;
            }
            else
            {
                head = head->next;
                head->pre = nullptr;
            }
            --size;
            delete p;
            return true;
        }
        bool Eject(T& value)
        {
            if (size == 0)
                return false;
            value = tail->value;
            NodeType* p = tail;
            if (size == 1)
            {
                head = tail = nullptr;
            }
            else
            {
                tail = tail->pre;
                tail->next = nullptr;
            }

            --size;
            delete p;
            return true;
        }
    private:
        void _push( NodeType* n)
        {
            if (size == 0)
            {
                head = n;
                head->next = nullptr;
                head->pre = nullptr;
                tail = head;
            }
            else
            {
                n->next = head;
                n->pre = nullptr;
                head->pre = n;
                head = n;
            }
            ++size;
        }
        void _insert( NodeType* n)
        {
            if (size == 0)
            {
                head = n;
                head->next = nullptr;
                head->pre = nullptr;
                tail = head;
            }
            else
            {
                tail->next = n;
                n->pre = tail;
                n->next = nullptr;
                tail = n;
            }
            ++size;
        }
        void _copy(const Deque& d)
        {
            NodeType* node = d.head;
            while (node)
            {
                NodeType* newNode = new NodeType(*node);
                _insert(newNode);
                node = node->next;
            }
        }
        void _destroy()
        {
            NodeType* node = head;
            while (node)
            {
                NodeType* p = node->next;
                delete node;
                node = p;
            }
            head = tail = nullptr;
            size = 0;
        }
    private:
        int size;
        NodeType* head;
        NodeType* tail;
    };
}

#endif

测试代码:

// Deque.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "Deque.h"
#include <iostream>
#include <deque>

using namespace std;

using namespace MyDataStructure;

int _tmain(int argc, _TCHAR* argv[])
{
    Deque<int> d;
    for (int i = 0; i < 10; ++i)
    {
        d.Insert(i);
    }
    Deque<int> d2;
    Deque<int> d1 = d2 = d;

    int value;
    for (int i = 0; i < 10; ++i)
    {
        if (d1.Eject(value))
            cout << value << ‘ ‘;
    }
    cout << endl;
    for (int i = 0; i < 10; ++i)
    {
        if (d2.Eject(value))
            cout << value << ‘ ‘;
    }
    cout << endl;
    for (int i = 0; i < 10; ++i)
    {
        if (d.Eject(value))
            cout << value << ‘ ‘;
    }
    cout << endl;
    cout << d.Size() << endl;
    d.Clear();
    d1.Clear();
    d2.Clear();
    return 0;
}

运行结果:

本次写博客的经验是:1)以后注释直接写在源文件里,不要到了写博客的时候才写在博文里。2)如果你是写了一半保存在线上,下次写完发表时,请先保存一下再发表,不然如果马上再来修改已经发表的文章的时候,只有之前的一半内容。已被坑死!

时间: 2024-10-21 18:47:42

每日一题22:Deque与Trait的相关文章

老男孩教育每日一题-2017年5月22日-命令风暴:变量a=’a/b/c’如何截取得到c

1.题目 2.参考答案 系统环境 [[email protected] ~]# uname -r2.6.32-504.el6.x86_64 [[email protected] ~]# cat /etc/redhat-releaseCentOS release 6.6 (Final) [[email protected] ~]# a='a/b/c' 方法1-cut [[email protected] ~]# echo $a | cut -c5c 方法2-tr替换 [[email protect

老男孩教育每日一题-2017年5月17日-使用三剑客进行变化格式

1.题目 原始数据: 17/Apr/2015:09:29:24 +0800 17/Apr/2015:09:30:26 +0800 17/Apr/2015:09:31:56 +0800 18/Apr/2015:09:34:12 +0800 18/Apr/2015:09:35:23 +0800 19/Apr/2015:09:23:34 +0800 19/Apr/2015:09:22:21 +0800 20/Apr/2015:09:45:22 +0800 期望结果: 2015-04-17 09:29:

C语言每日一题之No.9

再做决定之前,我还是做好自己该做的.我不希望几年后会悔恨自己为什么在最该努力的时候不愿意吃苦.尊敬的女王陛下,请接题: 一.题目:有已按升序排好顺序的字符串a,编写程序将字符串s中的每个字符按升序的规则插到字符串a中,最后输出"abdefghjkmnptwy". 二.思路:既然是已经排好序的,就用二分法查找的思想 将字符串s中的每个字符依次作为key拿来和字符串a做比较并且插入 三.程序 1 #include <stdio.h> 2 #include <string.

C语言每日一题之No.1

鉴于在学校弱弱的接触过C,基本上很少编程,C语言基础太薄弱.刚好目前从事的是软件编程,难度可想而知.严重影响工作效率,已无法再拖下去了.为此,痛下决心恶补C语言.此前只停留在看书,光看好像也记不住,C这东西毕竟是练出来的,所以从今天开始,每日一道C语言题目,从题目入手来补知识漏洞.题目比较基础,如不堪入目,还请见谅. 题目:输入三个整数,输出最大的数 思路:定义三个变量用来存储输入的整数 比较三个变量的大小,找到最大的数 定义一个变量存储来存储最大的数 程序: 1 #include <stdio

老男孩教育每日一题-2017年4月26日-通过访问日志access.log统计IP和每个地址访问的次数

通过访问日志access.log统计IP和每个地址访问的次数 101.226.61.184 - - [22/Nov/2015:11:02:00 +0800] "GET /mobile/sea-modules/gallery/zepto/1.1.3/zepto.js HTTP/1.1" 200 24662 "http://m.oldboyedu.com/mobile/theme/oldboyedu/home/index.html" "Mozilla/5.0 

老男孩教育每日一题-第101天-如何通过端口查找出进程所在目录?

参考答案: 第一步-找到端口对应的进程的号 [[email protected] ~]# ss -lntup |grep :22 tcp    LISTEN     0      128                   :::22                   :::*      users:(("sshd",1467,4)) tcp    LISTEN     0      128                    *:22                    *:*

老男孩教育每日一题-2017年5月8日-请根据以下数字信息,确认相应的端口号,端口号对应的服务名称

1.题目 老男孩教育每日一题-2017年5月8日-网络服务知识点:请根据以下数字信息,确认相应的端口号,端口号对应的服务名称,以及服务主要的作用(简要说明即可) 202122232567686980110111161 2.参考答案 端口号 端口号对应服务名称 服务作用说明 20/21(TCP) FTP服务端口 20端口为FTP传输数据用 21端口为FTP传输控制信息 文件传输协议(File Transfer Protocol) 由于FTP传输效率非常高,在网络上传输大的文件时,一般也采用该协议

老男孩教育每日一题-第87天-Nginx需要优化哪些内容?

参考答案: 1.gzip压缩优化2.expires缓存优化3.网络IO事件模型优化4.隐藏软件名称和版本号5.防盗链优化6.禁止恶意域名解析7.禁止通过IP地址访问网站.8.HTTP请求方法优化.9.防DOS攻击单IP并发连接的控制,与连接速率控制.10.严格设置Web站点目录的权限.11.将Nginx进程以及站点运行于监牢模式(nginx服务降权启动(不能使用80端口,使用其他端口,例如8080).站点目录设置普通用户).12.通过robot协议以及HTTP_USER_AGENT防爬虫优化13

C语言每日一题之No4.

这几天老大也没安排我什么项目,于是想正好趁着空补C.当然,是利用晚上加班时间,白天正常上班时间还是学习公司的平台. 今儿个突然弱弱的感觉到在公司补C是件很低级的事情,哪怕是在加班时间都会被喷,因为大家在关心Linux玩得顺溜不顺溜的情况下,我在补C,万恶的C.想想也是,这种最最基础的C语言只能自己挤出时间来补了,在公司最起码也得学点高端点的,比如Linux,如果作为一个软件开发人员,你不会Linux还搞毛线啊? 好吧,工作一天了,今日吐槽完毕,人生因吐槽而舒畅爽快 ,神一样的存在.此时此刻就是回