Set/Map

此代码是再BST.hLinkedList.h上的二次封装,阅读前请先了解底层代码。

Set

  • 基于链表的Set:Value是无序不重复的。
  • 基于BST的Set:Value是有序不重复的。

节点结构

template<typename T>
class BSTNode{
public:
    T e;    //节点元素
    BSTNode<T>*left;   //左节点
    BSTNode<T>*right;  //右节点
    
public:
    BSTNode(T E):e(E),left(nullptr),right(nullptr){}	//初始化
};
template<typename T>
class Node
{
public:
    T e;
    Node<T>*next;
    
public:
    Node():e(0),next(nullptr){}
    Node(T& E):e(E),next(nullptr){}
    Node(T& E,Node<T>*Next):e(E),next(Next){}
};

由于是底层链表和BST的二次封装所以和底层数据结构的节点相同。

Map

  • Map:是由Key和Value组成的键值对,由Key映射其对应的值Value。
  • 基于链表的Map:Key是无序不重复的。
  • 基于BST的Map:Key是有序不重复的。

节点结构

template<typename K,typename V>
class MapNode{
public:
    K key;
    V value;
    MapNode<K,V>*next;
public:
    MapNode():key(),value(),next(nullptr){}
    MapNode(K KEY,V VALUE,MapNode<K,V>*NEXT):key(KEY),value(VALUE),next(NEXT){}
};
template<typename K,typename V>
class BSTNode{
public:
    K key;
    V value;
    BSTNode<K,V>*left,*right;
public:
    BSTNode(K key,V value):key(key),value(value),left(nullptr),right(nullptr){}
    BSTNode(BSTNode<K,V>*node):key(node->key),value(node->value),left(node->left),right(node->right){}
};

实例

#ifndef C___FILEOPERATION_H
#define C___FILEOPERATION_H

#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include <cassert>

using namespace std;

namespace FileOps {

    bool isCharacter(char c) {
        return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
    }

    int firstCharacterIndex(const string &s, int start) {
        for (int i = start; i < s.length(); i++)
            if (isCharacter(s[i]))
                return i;
        return s.length();
    }

    string lowerS(const string &s) {
        string ret = "";
        for (int i = 0; i < s.length(); i++) {
            assert(isCharacter(s[i]));
            ret += tolower(s[i]);
        }
        return ret;
    }

    bool readFile(const string &filename, vector<string> &words) {
        string line;
        string contents = "";
        ifstream file(filename);
        if (file.is_open()) {
            while (getline(file, line))
                contents += (line + "
");
            file.close();
        } else {
            cout << "Can not open " << filename << " !!!" << endl;
            return false;
        }

        int start = firstCharacterIndex(contents, 0);
        int i;
        for (i = start + 1; i <= contents.length();) {

            if (i == contents.length() || !isalpha(contents[i])) {
                words.push_back(lowerS(contents.substr(start, i - start)));
                start = firstCharacterIndex(contents, i);
                i = start + 1;
            } else {
                i++;
            }
        }

        return true;
    }
}
#endif //C___FILEOPERATION_H

查询一本书有多少的单词

int main()
{
    std::cout << "a-tale-of-two-cities.txt" << std::endl;
    vector<string> words;
    if (FileOps::readFile(".././a-tale-of-two-cities.txt", words)) {
        std::cout << "Total words: " << words.size() << std::endl;
        BSTSet<string> *bstSet = new BSTSet<string>();
        for(string word : words) {
            bstSet->add(word);
        }
        std::cout << "Total different words: " << bstSet->getSize() << std::endl;
        bstSet = nullptr;
        delete bstSet;
    }

    std::cout << "pride-and-prejudice.txt" << std::endl;
    vector<string> words1;
    if (FileOps::readFile(".././pride-and-prejudice.txt", words1)) {
        std::cout << "Total words: " << words1.size() << std::endl;
        BSTSet<string> *bstSet = new BSTSet<string>();
        for(string word : words1) {
            bstSet->add(word);
        }
        std::cout << "Total different words: " << bstSet->getSize() << std::endl;
        bstSet = nullptr;
        delete bstSet;
    }
    return 0;
}

运行结果:
在这里插入图片描述

查询一本书有多少不重复的单词

int main()
{
    std::cout << "a-tale-of-two-cities.txt" << std::endl;
    string filename = ".././a-tale-of-two-cities.txt";
    BSTMap<string, int> *bstMap = new BSTMap<string, int>();
    vector<string> words;
    if (FileOps::readFile(filename, words)) {
        std::cout << "Total words: " << words.size() << std::endl;
        for (string word : words) {
            if (bstMap->contains(word)) {
                bstMap->set(word, *(bstMap->get(word)) + 1);
            } else {
                bstMap->add(word, 1);
            }
        }
        std::cout << "Total different words: " << bstMap->getSize() << std::endl;
        std::cout << "Frequency of PRIDE: " << *(bstMap->get("pride")) << std::endl;
        std::cout << "Frequency of PREJUDICE: " << *(bstMap->get("prejudice")) << std::endl;
    }
    return 0;
}

运行结果:
在这里插入图片描述

时间复杂度分析

Map

在这里插入图片描述

Set

在这里插入图片描述

代码清单

Set.h

#ifndef C___SET_H
#define C___SET_H

template<typename T>
class Set {
    virtual void add(T e) = 0;
    virtual void remove(T e) = 0;
    virtual bool contains(T e)const= 0;
    virtual int getSize()const= 0;
    virtual bool isEmpty()const= 0;
};
#endif //C___SET_H

BSTSet.h

#ifndef C___BSTSET_H
#define C___BSTSET_H
#include "Set.h"
#include "BST.h"

template<typename T>
class BSTSet: public Set<T> {
private:
    BST<T>*bst;
public:
    BSTSet(){
        new BSTSet<T>();
    }
    int getSize()const{
        return bst->getSize();
    }
    bool isEmpty()const{
        return bst->isEmpty();
    }
    void add(T e){
        bst->add(e);
    }
    void remove(T e){
        bst->RRemove(e);
    }
    bool contains(T e)const {
        return bst->contains(e);
    }
    ~BSTSet(){
        delete bst;
    }
};

#endif //C___BSTSET_H

LinkedListSet.h

#ifndef C___LINKEDLISTSET_H
#define C___LINKEDLISTSET_H
#include "LinkedList.h"
#include "Set.h"

template<typename T>
class LinkedListSet: public Set<T> {
private:
    LinkedList<T>*list;
public:
    LinkedListSet(){
        list = new LinkedList<T>();
    }

    int getSize()const{
        return list->getSize();
    }

    bool isEmpty()const {
        return list->isEmpty();
    }

    bool contains(T e)const {
        return list->contains(e);
    }

    void add(T e){
        if(!list->contains(e)){
            list->addFirst(e);
        }
    }

    void remove(T e){
        list->removeElement(e);
    }
    ~LinkedListSet(){
        delete list;
    }
};

#endif //C___LINKEDLISTSET_H

Map.h

#ifndef C___MAP_H
#define C___MAP_H

template<typename K,typename V>
class Map {
    virtual int getSize()const  = 0;
    virtual bool isEmpty()const = 0;
    virtual bool contains(K key) = 0;
    virtual void add(K key,V value) = 0;
    virtual V* get(K key) = 0;
    virtual void set(K key,V value) = 0;
    virtual V* remove(K key) = 0;
};
#endif //C___MAP_H

LinkedListMap.h

//
// Created by cmf on 2020/5/19.
//

#ifndef C___LINKEDLISTMAP_H
#define C___LINKEDLISTMAP_H
#include "Map.h"

template<typename K,typename V>
class MapNode{
public:
    K key;
    V value;
    MapNode<K,V>*next;
public:
    MapNode():key(),value(),next(nullptr){}
    MapNode(K KEY,V VALUE,MapNode<K,V>*NEXT):key(KEY),value(VALUE),next(NEXT){}
};

template<typename K,typename V>
class LinkedListMap : public Map<K,V>{
private:
    MapNode<K,V>*dummyHead;
    int size;
    MapNode<K,V>* getNode(K key){
        MapNode<K,V>*cur = dummyHead->next;
        while(cur!= nullptr){
            if(cur->key == key){
                return cur;
            }
            cur = cur->next;
        }
        return nullptr;
    }

public:
    LinkedListMap():size(0){
        dummyHead = new MapNode<K,V>();
    }
    int getSize()const{
        return size;
    }
    bool isEmpty()const {
        return size == 0;
    }
    bool contains(K key) {
        return getNode(key)!= nullptr;
    }
    V get(K key){
        if(contains(key) == true){
            MapNode<K,V>*node = getNode(key);
            return node->value;
        }
    }
    void set(K key,V value){
        MapNode<K,V>*node = getNode(key);
        if(node== nullptr){
            add(key,value);
        }else{
            node->value = value;
        }
    }
    void add(K key,V value){
        MapNode<K,V>*node = getNode(key);
        if(node == nullptr){
            dummyHead->next = new MapNode<K,V>(key,value,dummyHead->next);
            ++size;
        }else{
            node->value = value;
        }
    }
    V remove(K key){
        MapNode<K,V>*prev = dummyHead;
        while(prev->next!= nullptr){
            if(prev->next->key == key){
                break;
            }
            prev = prev->next;
        }
        if(prev->next!= nullptr){
            MapNode<K,V>*delNode = prev->next;
            prev->next = delNode->next;
            delNode->next = nullptr;
            --size;
            return delNode->value;
        }else{
            return prev->value;
        }
    }
};
#endif //C___LINKEDLISTMAP_H

BSTMap.h

#ifndef C___BSTMAP_H
#define C___BSTMAP_H
#include "Map.h"

template<typename K,typename V>
class BSTNode{
public:
    K key;
    V value;
    BSTNode<K,V>*left,*right;
    BSTNode(K key,V value):key(key),value(value),left(nullptr),right(nullptr){}
    BSTNode(BSTNode<K,V>*node):key(node->key),value(node->value),left(node->left),right(node->right){}
};

template<typename K,typename V>
class BSTMap :public Map<K,V>{
private:
    BSTNode<K,V>*root;
    int size;
public:
    int getSize()const{
        return size;
    }
    bool isEmpty()const{
        return size == 0;
    }
    BSTNode<K,V>*getNode(BSTNode<K,V>*node,K key){
        if(node == nullptr){
            return nullptr;
        }
        if(node->key == key){
            return node;
        }else if(node->key<key){
            return getNode(node->left,key);
        }else{
            return getNode(node->right,key);
        }
    }
    bool contains(K key){
        return getNode(root,key)!= nullptr;
    }

    void add(K key,V value){
        root = add(root,key,value);
    }
    V *get(K key) {
        BSTNode<K,V> *node = getNode(root, key);
        return node == nullptr ? nullptr : &(node->value);
    }
    void set(K key,V value){
        BSTNode<K,V>*node = getNode(root,key);
        if(node!= nullptr){
            node->value = value;
        }
    }
    V* remove(K key){
        BSTNode<K,V>*node = getNode(root,key);
        if(node!= nullptr){
            root = remove(root,key);
            return &(node->value);
        }
        return nullptr;
    }
    ~BSTMap(){
        destory(root);
    }
    BSTNode<K,V>* min(BSTNode<K,V>*node){
        if(node->left == nullptr){
            return node;
        }
        min(node->left);
    }
    BSTNode<K,V>* max(BSTNode<K,V>*node){
        if(node->right == nullptr){
            return node;
        }
        min(node->right);
    }
    BSTNode<K,V> *removeMin(BSTNode<K,V> *node) {
        if(node->left == nullptr){
            BSTNode<K,V>*rightNode = node->right;
            delete node;
            --size;
        }
        node->left = removeMin(node->left);
        return node;
    }
    BSTNode<K,V> *removeMax(BSTNode<K,V> *node) {
        if(node->right == nullptr){
            BSTNode<K,V>*rightNode = node->left;
            delete node;
            --size;
        }
        node->right = removeMin(node->right);
        return node;
    }
private:
    BSTNode<K,V>* add(BSTNode<K,V>*node,K key,V value){
        if(node == nullptr){
            ++size;
            return new BSTNode<K,V>(key,value);
        }
        if(key == node->key){
            node->value = node->value;
        }else if(key < node->key){
            node->left = add(node->left,key,value);
        }else{
            node->right = add(node->right,key,value);
        }
        return node;
    }
    void destory(BSTNode<K,V>*node){
        if(node!= nullptr){
            destory(node->left);
            destory(node->right);
            delete node;
            --size;
        }
    }
    BSTNode<K,V>*remove(BSTNode<K,V>*node,K key){
        if(node == nullptr){
            return nullptr;
        }
        if(node->key>key){
            node->left = remove(node->left,key);
            return node;
        }else if(node->key<key){
            node->right = remove(node->right,key);
            return node;
        }else {
            if (node->left == nullptr) {
                BSTNode<K, V> *rightNode = node->right;
                delete node;
                --size;
                return rightNode;
            }
            if (node->right == nullptr) {
                BSTNode<K, V> *leftNode = node->left;
                delete node;
                --size;
                return leftNode;
            }
            BSTNode<K, V> *succcessor = new BSTNode<K, V>(min(node->right));
            //Node *precursor = new Node(maximum(node->right));
            succcessor->right = removeMin(node->right);
            succcessor->left = node->left;
            //precursor->left = removeMax(node->left);
            //precursor->right = node->right;
            node->left = node->right = nullptr;
            delete node;
            return succcessor;
            //return precursor;
        }
    }
};
#endif //C___BSTMAP_H
原文地址:https://www.cnblogs.com/chengmf/p/12939262.html