Set/Map
此代码是再BST.h和LinkedList.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 + "\n");
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