数据结构与算法C++描述(9)---字典

来源:互联网 发布:微妙体育淘宝是真的吗 编辑:程序博客网 时间:2024/06/05 19:51

1.字典的概念

字典是一些节点的集合,每个节点包含数据域和key(键值)域。字典可以通过公式化描述或链表描述的方式创建。本文将通过链表描述的方式创建字典,字典的键值是依次递增的,并对字典进行如下操作:

  1. 字典的删除;
  2. 添加一个字典元素;
  3. 判断字典是否为空;
  4. 搜索键值为k的元素值;
  5. 获取字典中的元素个数;
  6. 在键值为k的节点中插入元素x,允许键值k已存在;
  7. 在键值为k的节点中插入元素x,不允许键值k存在,即字典中的每个键值只对应一个元素;
  8. 输出字典,重载“<<”。

2. 字典节点类的声明与实现

若利用链表来描述字典,必须首先声明链表中的每个节点,即建立链表节点类。在类中,每个节点包含key和data两个域。具体实现可参考注释。

/*------------------------------------字典类(有序链表)-----------------------------------*/template <class E,class K> class DictionaryChain;template <class E,class K>class DictionaryChainNode{    //为了让类DictionaryChain访问本类的成员,将其声明为本类的友类    friend DictionaryChain<E,K>;public:    //链表节点默认构造函数,将data设为0,并指向NULL    DictionaryChainNode() :data(0) { link = NULL; }    //链表节点类构造函数,建立键值key=k,数据data=e的节点,并指向NULL    DictionaryChainNode(const K &k,const E &e) :data(e), key(k) { link = NULL; }    DictionaryChainNode<E, K> *getLink() {  //获取下一个节点        if (link)            return link;        return NULL;    }private:      E data;                                //数据    K key;                                 //键值    DictionaryChainNode<E,K> *link;        //指向下一个节点};

3. 字典类的声明与实现

3.1 字典类的声明与简单函数的实现

template <class E,class K>class DictionaryChain{public:    //默认构造函数,头节点first指向NULL    DictionaryChain() { first = NULL; }                             //建立字典    //构造初始节点的键值为k,数据data=e的字典对象    DictionaryChain(const K &k,const E &e)    {        first = new DictionaryChainNode<E, K>(k, e);    }    ~DictionaryChain();                                             //删除字典    bool IsEmpty() { return first == NULL; }                        //判断字典是否为空    int Length()const;                                              //返回字典大小    bool Search(const K&k, E &e);                                   //寻找键值为k的元素,并赋给e    DictionaryChain<E, K>& Delete(const K&k, E &e);                 //删除键值为k的元素,并赋值给e,返回操作后的字典    DictionaryChain<E, K>& Insert(const K&k, const E&e);            //在字典中插入元素e,并返回操作后的字典,允许有相同的关键字    DictionaryChain<E, K>& DistinctInsert(const K&k,const E &e);    //插入元素操作,不允许有相同的关键字    void Output(ostream &out)                                       //输出字典    {        DictionaryChainNode<E, K> *current = first;        while (current)        {            out <<"("<< current->key << ": " << current->data<<")" << ";  ";            current = current->getLink();                           //指向下一节点        }        cout << endl;    }private:    DictionaryChainNode<E, K> *first;                               //头节点指针};

3.2 字典的删除—析构函数的实现

通过依次删除字典中的每个节点,实现字典的删除。

//析构函数template<class E,class K>DictionaryChain<E, K>::~DictionaryChain(){    DictionaryChainNode<E, K> *next;    while (first)                                  //若first不为0,即链表不为空,则继续删除节点    {        next = first->getLink();                   //指向下一个节点        delete first;                              //删除当前节点        first = next;                              //循环    }}

3.3 获取字典中元素的个数

//获取链表长度template<class E, class K>int DictionaryChain<E, K>::Length() const{    int len = 0;                            //记录链表长度    DictionaryChainNode<E,K> *next=first;   //声明中间节点    while (next)                            //只要未到末节点,则len++    {        len++;                              //长度+1        next = next->getLink();             //指向下一个节点    }    return len;                             //返回链表长度}

3.4 在字典中寻找键值为k的元素,并将其数据赋给e

在此要注意,利用链表描述字典时,字典的键值是依次递增的!!!

//寻找键值为k的元素,并赋给etemplate<class E, class K>bool DictionaryChain<E,K>::Search(const K&k, E &e){//搜索与k匹配的元素,结果放入e中。若存在,返回true;否则,返回false。    DictionaryChainNode<E, K> *next = first;    while (next && next->key < k)    //移动到key值为k的节点        next = next->link;    if (next && next->key == k)      //判断    {        e = next->data;              //赋值        return true;    }    return false;                                   }

3.5 删除键值为k的元素,并赋值给e,返回操作后的字典

//删除键值为k的元素,并赋值给e,返回操作后的字典template <class E,class K>DictionaryChain<E, K>& DictionaryChain<E, K>::Delete(const K&k, E &e){    DictionaryChainNode<E, K> *next=first,*t=0;    while (next && next->key < k)                               //移动到t移动到k-1处,next移动到k处    {        t = next;        next = next->link;    }    if (next && next->key == k) {                               //确认是否为k        e = next->data;                                         //获取第k个节点元素值        if (t)                                                  //当前节点不是首节点,即链表不为空            t->link = next->link;                               //将第k-1个节点指向第k+1个节点        else                                                    //若是首节点,即链表为空            first = next->link;                                 //指向下一个节点        delete next;                                            //删除第k个节点        return *this;    }    else                                                        //若不等于k,则抛出输入错误异常        throw BadInput();}

3.6 在字典中插入元素e,并返回操作后的字典,允许有相同的键值

//在字典中插入元素e,并返回操作后的字典,允许有相同的键值template <class E, class K>DictionaryChain<E, K>& DictionaryChain<E, K>::Insert(const K&k,const E&e){    DictionaryChainNode<E, K> *next=first,*t=0;     while (next && next->key < k)                               //移动到t移动到k-1处,next移动到k处    {        t = next;          next = next->link;                                      //指向元素e的前一个位置    }    DictionaryChainNode<E, K> *p = new DictionaryChainNode<E,K>(k,e);   //新建节点       //插入节点p         p->link = next;    if (t)                                                      //t不为首节点        t->link = p;                                            //将p插入next之后    else                                                        //next为首节点,即链表为空        first = p;                                              //设置p为首节点    return *this;}

3.7 插入元素操作,不允许有相同的键值

//插入元素操作,不允许有相同的关键字template <class E, class K>DictionaryChain<E, K>& DictionaryChain<E,K>::DistinctInsert(const K &k,const E &e){    DictionaryChainNode<E, K> *next = first,*t=0;    while (next && next->key < k)                               //移动到t移动到k-1处,next移动到k处    {        t = next;        next = next->link;    }    if (next && next->key == k)                                 //如果已经存在e节点,则抛出异常        throw BadInput();    DictionaryChainNode<E, K> *q = new DictionaryChainNode<E, K>(k,e);  //新建节点    //q->data = e;    q->link = next;    if (t)                                                      //链表不为空        t->link = q;    else        first = q;    return *this;}

3.8 重载操作符”<<”

//重载操作符“<<”template <class E, class K>ostream& operator<<(ostream &out, DictionaryChain<E, K> &S){    S.Output(out);    return out;}

4 测试

4.1 测试样例

这里写图片描述

4.2 测试结果

这里写图片描述


参考:
[1] 数据结构算法与应用:C++描述(Data Structures, Algorithms and Applications in C++ 的中文版)
[2] http://www.cnblogs.com/haoliuhust/p/4420618.html

阅读全文
0 0