容器—结构与分类
1、Sequence Containers——序列式容器
2、Associative Containers——关联式容器
3、(C++11)Unordered Containers——不定序容器
1、Sequence Containers(红色为C++11新特性)
2、Associative Containers——关联式容器
内部使用红黑树实现的——Set&Map
3、(C++11)Unordered Containers——不定序容器
1)分类结构
2)红色框中标注的是C++11开始有的容器
3)Array数组容器,大小固定的
4)Deque:两段都可以进行插入删除操作,但是从内存上讲不通,怎么实现的要从后面的学习知道。
5)List:是一个双向的循环链表,注意是双向的。
6)Forward-List:单向链表,当能用单向链表的时候尽量用,可以减少内存空间,一个指针在32位pc上占4个字节,当数据量很多上百万,不可忽略!
7)Set键值都一样,MultiSet允许元素有重复。
8)Set/Map用红黑树实现,RB-tree是自平衡的二叉树。
9)Unorder Containers:是C++标准库里卖的内容。
根据这些图例,可以知道这些容器在内存用到的数据结构是什么样的。
HashTable实现方法很多,但基本都用Separate Chaining(分离链地址法实现)。
以下测试程序之辅助函数
#include <iostream>
using std::cin;
using std::cout;
using std::string;
long get_a_target_long() //交互式方式让使用者输入一个要找的目标
{
long target = 0;
cout << "target { 0~" << RAND_MAX << "): ";
cin >> target;
return target;
}
string get_a_target_string() //字符串
{
long target = 0;
char buf[10];
cout << "target { 0~" << RAND_MAX << "): ";
cin >> target;
snprintf(buf, 10, "%d", target); //转换为字符串
return string(buf);
}
int compareLongs(const void* a, const void* b) //比较两个long等不等
{
return (*(long*)a - *(long*)b);
}
int compareStrings(const void* a, const void* b) //比较两个string等不等
{
if (*(string*)a > *(string*)b)
return 1;
else if (*(string*)a < *(string*)b)
return -1;
else
return 0;
}
使用容器array
1)指针void* a -> *(long*)a;
2)array<long, size> c使用初始化大小,#include<array>
3)c.data()返回这个数组的初始地址,和数组的地址对比
4)qsort应用:qsort(c.data,size,size(long),comparelongs)
5)bsearch()应用,查找前必须排好序了:bsearch(&target,(c.data()),size,size(long),comparelongs)
6)qsort,bsearch包含头文件#include<cstdlib>,C本身库函数
//以下测试程序之辅助函数
#include <array>
#include <iostream>
#include <ctime>
#include <cstdlib> //qsort, bsearch , NULL
#include <string>
using namespace std;
#define ASIZE 100000
long get_a_target_long() //交互式方式让使用者输入一个要找的目标
{
long target = 0;
cout << "target { 0~" << RAND_MAX << "): ";
cin >> target;
return target;
}
string get_a_target_string() //字符串
{
long target = 0;
char buf[10];
cout << "target { 0~" << RAND_MAX << "): ";
cin >> target;
snprintf(buf, 10, "%d", target); //转换为字符串
return string(buf);
}
int compareLongs(const void* a, const void* b) //比较两个long等不等
{
return (*(long*)a - *(long*)b);
}
int compareStrings(const void* a, const void* b) //比较两个string等不等
{
if (*(string*)a > *(string*)b)
return 1;
else if (*(string*)a < *(string*)b)
return -1;
else
return 0;
}
//使用容器array测试
namespace jj01
{
void text_array()
{
cout << "\ntest_array().......... \n";
array<long, ASIZE> c;
clock_t timeStart = clock();
for (long i = 0; i < ASIZE; ++i)
{
c[i] = rand();
}
cout << "milli-seconds :" << (clock() - timeStart) << endl;
cout << "array.size() = " << c.size() << endl;
cout << "array.front() = " << c.front() << endl;
cout << "array.back() = " << c.back() << endl;
cout << "array.data() = " << c.data() << endl;
long target = get_a_target_long();
timeStart = clock();
qsort(c.data(), ASIZE, sizeof(long), compareLongs);
long* pItem = (long*)bsearch(&target, (c.data()), ASIZE, sizeof(long), compareLongs);
cout << "qsort() + bsearch(), milli-seconds:" << (clock() - timeStart) << endl;
if (pItem != NULL)
cout << "found, " << *pItem << endl;
else
cout << "not found!" << endl;
}
}
int main()
{
jj01::text_array();
return 0;
}
结果
test_array()..........
milli-seconds :20
array.size() = 100000
array.front() = 41
array.back() = 1629
array.data() = 00C9DDD0
target { 0~32767): 2000
qsort() + bsearch(), milli-seconds:94
found, 2000
封装成类
jj01.h
#pragma once
#include <array>
#include <iostream>
#include <ctime>
#include <cstdlib> //qsort, bsearch , NULL
#include <string>
using namespace std;
class jj01
{
public:
jj01();
~jj01();
void test_array();
};
jj01.cpp
#include "jj01.h"
#include "Fzhs.h"
#define ASIZE 100000
jj01::jj01()
{
}
int compareLongs(const void* a, const void* b) //比较两个long等不等
{
return (*(long*)a - *(long*)b);
}
void jj01::test_array()
{
Fzhs* fzhs = new Fzhs;
cout << "\ntest_array().......... \n";
array<long, ASIZE> c; //定义一个类型为long、ASIZE大小的数组c
clock_t timeStart = clock();
for (long i = 0; i < ASIZE; ++i)
{
c[i] = rand();
}
cout << "milli-seconds :" << (clock() - timeStart) << endl;
cout << "array.size() = " << c.size() << endl; //大小
cout << "array.front() = " << c.front() << endl; // 第一个元素
cout << "array.back() = " << c.back() << endl; //最后一个元素
cout << "array.data() = " << c.data() << endl; //传回这个数组起点的地址
long target = fzhs->get_a_target_long();
timeStart = clock();//开始计时
qsort(c.data(), ASIZE, sizeof(long), compareLongs); //起点地址, 数组大小、每个元素的大小、比大小。排序
long* pItem = (long*)bsearch(&target, (c.data()), ASIZE, sizeof(long), compareLongs); //二分查找
cout << "qsort() + bsearch(), milli-seconds:" << (clock() - timeStart) << endl;
if (pItem != NULL)
cout << "found, " << *pItem << endl;
else
cout << "not found!" << endl;
delete fzhs;
}
jj01::~jj01()
{
}
辅助函数Fzhs.h
#pragma once
#include <string>
#include <iostream>
using namespace std;
class Fzhs
{
public:
Fzhs();
~Fzhs();
long get_a_target_long();
string get_a_target_string();
int compareLongs(const void*, const void*);
int compareStrings(const void*, const void*);
};
Fzhs.cpp
#include "Fzhs.h"
Fzhs::Fzhs()
{
}
long Fzhs::get_a_target_long() //交互式方式让使用者输入一个要找的目标
{
long target = 0;
cout << "target { 0~" << RAND_MAX << "): ";
cin >> target;
return target;
}
string Fzhs::get_a_target_string() //字符串
{
long target = 0;
char buf[10];
cout << "target { 0~" << RAND_MAX << "): ";
cin >> target;
snprintf(buf, 10, "%d", target); //转换为字符串
return string(buf);
}
int Fzhs::compareLongs(const void* a, const void* b) //比较两个long等不等
{
return (*(long*)a - *(long*)b);
}
int Fzhs::compareStrings(const void* a, const void* b) //比较两个string等不等
{
if (*(string*)a > *(string*)b)
return 1;
else if (*(string*)a < *(string*)b)
return -1;
else
return 0;
}
Fzhs::~Fzhs()
{
}
main.cpp
//以下测试程序之辅助函数
#include "jj01.h"
//使用容器array测试
int main()
{
jj01* j1 = new jj01;
j1->test_array();
delete j1;
return 0;
}
容器之分类与各种测试(二)——vector
测试Vector
主要通过程序细节说明
namespace命名空间的说明
1)vector的增长速度是2倍增长,当capacity不够时,
容量增长为前面的2倍。是在另外的2倍空间!
2)try...catch...捕获函数,字符串最大占一个指针大小,
空间不够的时候抛出,abort()退出
3)::find()模板函数,加冒号表明是全局函数,当没有冒号时,
编译器在当前没有找到,也会到全局去找。
4)用两种查找算法比较,find()用时更少。
jj02.h
#pragma once
#include <vector>
#include <stdexcept>
#include <string>
#include <cstdlib>
#include <cstdio> //abort()
#include <iostream>
#include <ctime>
#include <algorithm> //sort()
using namespace std;
class jj02
{
public:
jj02();
~jj02();
void test_vector(long&);
};
jj02.cpp
#include "jj02.h"
#include "Fzhs.h"
int compareStrings(const void* a, const void* b) //比较两个string等不等
{
if (*(string*)a > *(string*)b)
return 1;
else if (*(string*)a < *(string*)b)
return -1;
else
return 0;
}
jj02::jj02()
{
}
void jj02::test_vector(long& value)
{
Fzhs* f1 = new Fzhs;
cout << "\ntest_vector().........\n";
vector<string> c;
char buf[10];
clock_t timeStart = clock();
for (long i = 0; i < value; ++ i)
{
try //抓取异常的发生
{
snprintf(buf, 10, "%d", rand());
c.push_back(string(buf)); // vector 容器放元素的操作,放在后面,空间不够,两倍增长
}
catch (exception& p)
{
cout << "i = " << " " << p.what() << endl;
//曾经最高 i = 58389486 then std::bad_alloc
abort(); //发生异常,退出程序
}
}
cout << "milli-seconds :" << (clock() - timeStart) << endl;
cout << "vector.size() = " << c.size() << endl; //大小
cout << "vector.front() = " << c.front() << endl; // 第一个元素
cout << "vector.back() = " << c.back() << endl; //最后一个元素
cout << "vector.data() = " << c.data() << endl; //传回这个数组起点的地址
cout << "vector.capacity() = " << c.capacity() << endl; //目前空间有多大
string target = f1->get_a_target_string();
{
timeStart = clock();
auto pItem = find(c.begin(), c.end(), target); //模板函数
cout << "std::find(), milli-seconds : " << (clock() - timeStart) << endl;
if (pItem != c.end())
cout << "found, " << *pItem << endl;
else
cout << "not found!" << endl;
}
{
timeStart = clock();
sort(c.begin(), c.end()); //sort时间很慢
string* pItem = (string*)::bsearch(&target, (c.data()), c.size(), sizeof(string), compareStrings); //二分查找
cout << "sort() + brearch(), milli-seconds : " << (clock() - timeStart) << endl;
if (pItem != NULL)
cout << "found, " << *pItem << endl;
else
cout << "not found!" << endl;
}
c.clear();
}
jj02::~jj02()
{
}
main.cpp
//以下测试程序之辅助函数
#include "jj01.h"
#include "jj02.h"
//使用容器array测试
int main()
{
/*jj01* j1 = new jj01;
j1->test_array();
delete j1;*/
jj02* j2 = new jj02;
long value;
cin >> value;
cout << "how many element:" << value << endl;
j2->test_vector(value);
delete j2;
return 0;
}
结果:
100000
how many element:100000
test_vector().........
milli-seconds :3548
vector.size() = 100000
vector.front() = 41
vector.back() = 1629
vector.data() = 01513060
vector.capacity() = 138255
target { 0~32767): 23456
std::find(), milli-seconds : 28
found, 23456
sort() + brearch(), milli-seconds : 6783
found, 23456
容器之分类与各种测试(三)——使用容器list
测试List,双向链表
1)list.max_size()按理list是动态申请空间的,为什么最大的size呢?
2)list双向链表实现
3)有趣的c.sort(),这里注意在STL标准库全局有一个sort函数,但这里调用的是list容器自身内部的sort函数。注意在STL容器中有些自身有sort函数,此时用自身的排序算法更快。
jj03.h
#pragma once
#include <iostream>
#include <list>
#include <string>
#include <stdexcept>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <ctime>
using namespace std;
class jj03
{
public:
jj03();
~jj03();
void test_list(long&);
};
jj03.cpp
#include "jj03.h"
#include "Fzhs.h"
jj03::jj03()
{
}
void jj03::test_list(long& value)
{
Fzhs* f1 = new Fzhs;
cout << "\ntest_list().............\n";
list<string> c;
char buf[10];
clock_t timeStart = clock();
for (long i = 0; i < value; ++i)
{
try
{
snprintf(buf, 10, "%d", rand());
c.push_back(string(buf));
}
catch (exception& p)
{
cout << "i =" << i << " " << p.what() << endl;
abort();
}
}
cout << "milli-seconds :" << (clock() - timeStart) << endl;
cout << "list.size() = " << c.size() << endl; //大小
cout << "list.max_size() = " << c.max_size() << endl; //最大放多少——我不知道——哈哈哈
cout << "list.front() = " << c.front() << endl; // 第一个元素
cout << "list.back() = " << c.back() << endl; //最后一个元素
string target = f1->get_a_target_string();
timeStart = clock();
auto pItem = ::find(c.begin(), c.end(), target);
cout << "::find(), milli-seconds : " << (clock() - timeStart) << endl;
if (pItem != c.end())
cout << "found :" << *pItem << endl;
else
cout << "not found!" << endl;
timeStart = clock();
c.sort();//容器里面自己的排序方法、某些容器会自带sort
cout << "c.sort(), milli-seconds : " << (clock() - timeStart) << endl;
}
jj03::~jj03()
{
}
main.cpp
//以下测试程序之辅助函数
#include "jj01.h"
#include "jj02.h"
#include "jj03.h"
//使用容器array测试
int main()
{
/*jj01* j1 = new jj01;
j1->test_array();
delete j1;*/
//jj02* j2 = new jj02;
//long value;
//cin >> value;
//cout << "how many element:" << value << endl;
//j2->test_vector(value);
//delete j2;
jj03* j3 = new jj03;
long value;
cin >> value;
cout << "how many element: " << value << endl;
j3->test_list(value);
delete j3;
return 0;
}
结果
1000000
how many element: 1000000
test_list().............
milli-seconds :16316
list.size() = 1000000
list.max_size() = 119304647
list.front() = 41
list.back() = 12679
target { 0~32767): 23456
::find(), milli-seconds : 38
found :23456
c.sort(), milli-seconds : 178467
容器之分类与各种测试——使用容器forward_list
1)forward-list单向链表,C++11出现的
2)push_front在链表头插入,不提供在尾部插入,效率低些。
3)front取链表头的元素,不提供back()操作取链表尾的元素。
c.sort()用它自身的排序算法
jj04.h
#pragma once
#include <iostream>
#include <forward_list>
#include <string>
#include <stdexcept>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <ctime>
using namespace std;
class jj04
{
public:
jj04();
~jj04();
void test_forward_list(long&);
};
jj04.cpp
#include "jj04.h"
#include "Fzhs.h"
jj04::jj04()
{
}
void jj04::test_forward_list(long& value)
{
Fzhs* f1 = new Fzhs;
cout << "\ntest_forward_list()........\n";
forward_list<string> c;
char buf[10];
clock_t timeStart = clock();
for (long i = 0; i < value; ++i)
{
try
{
snprintf(buf, 10, "%d", rand());
c.push_front(string(buf));
}
catch (exception& p)
{
cout << "i = " << i << " " << p.what() << endl;
abort();
}
}
cout << "milli-seconds :" << (clock() - timeStart) << endl;
cout << "forward_list.max_size() = " << c.max_size() << endl; //最大放多少——我不知道——哈哈哈
cout << "forward_list.front() = " << c.front() << endl; // 第一个元素
//cout << "forward_list.back() = " << c.back() << endl; //最后一个元素 no such member function
string target = f1->get_a_target_string();
timeStart = clock();
auto pItem = ::find(c.begin(), c.end(), target);
cout << "::find(), milli-seconds : " << (clock() - timeStart) << endl;
if (pItem != c.end())
cout << "found: " << *pItem << endl;
else
cout << "not found!" << endl;
timeStart = clock();
c.sort();
cout << "c.sort(), milli-seconds : " << (clock() - timeStart) << endl;
delete f1;
}
jj04::~jj04()
{
}
main.cpp
//以下测试程序之辅助函数
#include "jj01.h"
#include "jj02.h"
#include "jj03.h"
#include "jj04.h"
//使用容器array测试
int main()
{
/*jj01* j1 = new jj01;
j1->test_array();
delete j1;*/
//jj02* j2 = new jj02;
//long value;
//cin >> value;
//cout << "how many element:" << value << endl;
//j2->test_vector(value);
//delete j2;
//jj03* j3 = new jj03;
//long value;
//cin >> value;
//cout << "how many element: " << value << endl;
//j3->test_list(value);
//delete j3;
jj04* j4 = new jj04;
long value;
cin >> value;
cout << "how many element : " << value << endl;
j4->test_forward_list(value);
delete j4;
return 0;
}
实验结果
100000
how many element : 100000
test_forward_list()........
milli-seconds :1071
forward_list.max_size() = 134217727
forward_list.front() = 1629
target { 0~32767): 23456
::find(), milli-seconds : 7
found: 23456
c.sort(), milli-seconds : 14083
容器之分类与各种测试(三)——使用容器slist
测试slist
Gnu C之前的单链表,forward-list是C++11才出现的
#include <ext\slist>
//注意, 上一行並沒有引發警告訊息如 #include <ext\hash_set> 所引發者:
//...\4.9.2\include\c++\backward\backward_warning.h
//[Warning] ...
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio> //snprintf()
#include <iostream>
#include <ctime>
namespace jj10
{
void test_slist(long& value)
{
cout << "\ntest_slist().......... \n";
__gnu_cxx::slist<string> c;
char buf[10];
clock_t timeStart = clock();
for(long i=0; i< value; ++i)
{
try {
snprintf(buf, 10, "%d", rand());
c.push_front(string(buf));
}
catch(exception& p) {
cout << "i=" << i << " " << p.what() << endl;
abort();
}
}
cout << "milli-seconds : " << (clock()-timeStart) << endl;
}
}
此部分我并没有去实现,要用G++编译器,我开始使用的是vs2017,没有slist头文件,实现有错~最好在linux + G++下测试(本人是windows + vs2017,所有有很多坑要填)
后续
因为我曾经玩过QT,QT自带了g++编译器,它是有标准库slist的,
结果
容器之分类与各种测试(三)——使用容器deque
1)测试deque
2)双向开口,是分段连续,感觉是连续的,其实不是。
3)内存上两边都可以扩充
4)每次512扩充,两边扩充申请buffer,buffer由指针指向
max_size由限制,使用全局的sort排序
jj05.h
#pragma once
#include <deque>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio> //snprintf()
#include <iostream>
#include <ctime>
#include <algorithm>
using namespace std;
class jj05
{
public:
jj05();
~jj05();
void test_deque(long& value);
};
jj05.cpp
#include "jj05.h"
#include "Fzhs.h"
jj05::jj05()
{
}
void jj05::test_deque(long& value)
{
Fzhs* f1 = new Fzhs;
cout << "\ntest_deque()........\n";
deque<string> c;
char buf[10];
clock_t timeStart = clock();
for (long i = 0; i < value; ++i)
{
try
{
snprintf(buf, 10, "%d", rand());
c.push_back(string(buf));
}
catch (exception& p)
{
cout << "i =" << " " << p.what() << endl;
abort();
}
}
cout << "milli- seconds : " << (clock() - timeStart) << endl;
cout << "deque.size() = " << c.size() << endl;
cout << "deque.front() = " << c.front() << endl;
cout << "deque.back() = " << c.back() << endl;
cout << "deque.max_size() = " << c.max_size() << endl;
string target = f1->get_a_target_string();
timeStart = clock();
auto pItem = ::find(c.begin(), c.end(), target);
cout << "::find(), milli-seconds : " << (clock() - timeStart) << endl;
if (pItem != c.end())
cout << "found, " << *pItem << endl;
else
cout << "not found!" << endl;
timeStart = clock();
sort(c.begin(), c.end());
cout << "sort(), milli-seconds :" << (clock() - timeStart) << endl;
}
jj05::~jj05()
{
}
main.cpp
//以下测试程序之辅助函数
#include "jj01.h"
#include "jj02.h"
#include "jj03.h"
#include "jj04.h"
#include "jj05.h"
//使用容器array测试
int main()
{
/*jj01* j1 = new jj01;
j1->test_array();
delete j1;*/
//jj02* j2 = new jj02;
//long value;
//cin >> value;
//cout << "how many element:" << value << endl;
//j2->test_vector(value);
//delete j2;
//jj03* j3 = new jj03;
//long value;
//cin >> value;
//cout << "how many element: " << value << endl;
//j3->test_list(value);
//delete j3;
//jj04* j4 = new jj04;
//long value;
//cin >> value;
//cout << "how many element : " << value << endl;
//j4->test_forward_list(value);
//delete j4;
jj05* j5 = new jj05;
long value;
cin >> value;
j5->test_deque(value);
delete j5;
return 0;
}
结果
1000000
test_deque()........
milli- seconds : 10715
deque.size() = 1000000
deque.front() = 41
deque.back() = 12679
deque.max_size() = 153391689
target { 0~32767): 232
::find(), milli-seconds : 38
found, 232
sort(), milli-seconds :47788
使用容器stack
jj17.h
#pragma once
#include <iostream>
#include <string>
#include <ctime>
#include <stack>
#include <cstdlib>
#include <cstdio>
#include <stdexcept>
using namespace std;
class jj17
{
public:
jj17();
~jj17();
void test_stack(long& value);
};
jj17.cpp
#include "jj17.h"
jj17::jj17()
{
}
void jj17::test_stack(long& value)
{
cout << "\ntest_stack()...........\n";
stack<string> c;
char buf[10];
clock_t timeStart = clock();
for (long i = 0; i < value; ++i)
{
try
{
snprintf(buf, 10, "%d", rand());
c.push(string(buf));
}
catch(exception& p)
{
cout << "i =" << " " << p.what() << endl;
abort();
}
}
cout << "milli-seconds : " << (clock() - timeStart) << endl;
cout << "stack.size() = " << c.size() << endl;
cout << "stack.top() = " << c.top() << endl;
c.pop();
cout << "stack.size() = " << c.size() << endl;
cout << "stack.top() = " << c.top() << endl;
}
jj17::~jj17()
{
}
main.cpp
//以下测试程序之辅助函数
#include "jj01.h"
#include "jj02.h"
#include "jj03.h"
#include "jj04.h"
#include "jj05.h"
#include "jj17.h"
//使用容器array测试
int main()
{
/*jj01* j1 = new jj01;
j1->test_array();
delete j1;*/
//jj02* j2 = new jj02;
//long value;
//cin >> value;
//cout << "how many element:" << value << endl;
//j2->test_vector(value);
//delete j2;
//jj03* j3 = new jj03;
//long value;
//cin >> value;
//cout << "how many element: " << value << endl;
//j3->test_list(value);
//delete j3;
//jj04* j4 = new jj04;
//long value;
//cin >> value;
//cout << "how many element : " << value << endl;
//j4->test_forward_list(value);
//delete j4;
/*jj05* j5 = new jj05;
long value;
cin >> value;
cout << "how many element : " << value << endl;
j5->test_deque(value);
delete j5;*/
jj17* j6 = new jj17;
long value;
cin >> value;
cout << "how many element : " << value << endl;
j6->test_stack(value);
delete j6;
return 0;
}
结果
1000000
how many element : 1000000
test_stack()...........
milli-seconds : 9971
stack.size() = 1000000
stack.top() = 12679
stack.size() = 999999
stack.top() = 17172
使用容器queue
jj18.h
#pragma once
#include <queue>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio> //snprintf()
#include <iostream>
#include <ctime>
using namespace std;
class jj18
{
public:
jj18();
~jj18();
void test_queue(long&);
};
jj18.cpp
#include "jj18.h"
jj18::jj18()
{
}
void jj18::test_queue(long& value)
{
cout << "\ntest_queue()........\n";
queue<string> c;
char buf[10];
clock_t timeStart = clock();
for (long i = 0; i < value; ++i)
{
try
{
snprintf(buf, 10, "%d", rand());
c.push(string(buf));
}
catch (exception& p)
{
cout << "i = " << i << " " << p.what() << endl;
abort();
}
}
cout << "milli-seconds : " << (clock() - timeStart) << endl;
cout << "queue.size() = " << c.size() << endl;
cout << "queue.front() = " << c.front() << endl;
cout << "queue.back() = " << c.back() << endl;
c.pop();
cout << "queue.size() = " << c.size() << endl;
cout << "queue.front() = " << c.front() << endl;
cout << "queue.back() = " << c.back() << endl;
}
jj18::~jj18()
{
}
main.cpp
//以下测试程序之辅助函数
#include "jj01.h"
#include "jj02.h"
#include "jj03.h"
#include "jj04.h"
#include "jj05.h"
#include "jj17.h"
#include "jj18.h"
//使用容器array测试
int main()
{
jj18* j7 = new jj18;
long value;
cin >> value;
cout << "how many element : " << value << endl;
j7->test_queue(value);
delete j7;
return 0;
}
结果
1000000
how many element : 1000000
test_queue()........
milli-seconds : 10337
queue.size() = 1000000
queue.front() = 41
queue.back() = 12679
queue.size() = 999999
queue.front() = 18467
queue.back() = 12679
容器之分类与各种测试(四)
使用容器multiset允许元素重复
内部是红黑树,insert操作就保证了排好了序。
标准库有个::find()函数,大家都可以用。容器本身也有一个c.find(),通过键值对查找非常快!
jj06.h
#pragma once
#include <set>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio> //snprintf()
#include <iostream>
#include <ctime>
using namespace std;
class jj06
{
public:
jj06();
~jj06();
void test_multiset(long& value);
};
jj06.cpp
#include "jj06.h"
#include "Fzhs.h"
jj06::jj06()
{
}
void jj06::test_multiset(long& value)
{
Fzhs* f1 = new Fzhs;
cout << "\ntest_multiset().........\n";
multiset<string> c;
char buf[10];
clock_t timeStart = clock();
for (long i = 0; i < value; ++i)
{
try
{
snprintf(buf, 10, "%d", rand());
c.insert(string(buf));
}
catch (exception& p)
{
cout << "i = " << " " << p.what() << endl;
abort();
}
}
cout << "multi-seconds : " << (clock() - timeStart) << endl;
cout << "multiset.set() = " << c.size() << endl;
cout << "multiset.max_size() = " << c.max_size() << endl;
string target = f1->get_a_target_string();
{
timeStart = clock();
auto pItem = ::find(c.begin(), c.end(), target);
cout << "::find(), multi-seconds : " << (clock() - timeStart) << endl;
if (pItem != c.end())
{
cout << "found, " << *pItem << endl;
}
else
{
cout << "not found!" << endl;
}
{
timeStart = clock();
auto pItem = c.find(target); //比::find()快很多
cout << "c.find(), multi-seconds : " << (clock() - timeStart) << endl;
if (pItem != c.end())
cout << "found, " << *pItem << endl;
else
cout << "not found!" << endl;
}
}
}
jj06::~jj06()
{
}
main.cpp
//以下测试程序之辅助函数
#include "jj01.h"
#include "jj02.h"
#include "jj03.h"
#include "jj04.h"
#include "jj05.h"
#include "jj17.h"
#include "jj18.h"
#include "jj06.h"
//使用容器array测试
int main()
{
jj06* j8 = new jj06;
long value;
cin >> value;
cout << "how many element : " << value << endl;
j8->test_multiset(value);
delete j8;
return 0;
}
结果
1000000
how many element : 1000000
test_multiset().........
multi-seconds : 61226
multiset.set() = 1000000
multiset.max_size() = 97612893
target { 0~32767): 23456
::find(), multi-seconds : 630
found, 23456
c.find(), multi-seconds : 0
found, 23456
使用容器multimap
1)使用容器multimap(允许元素重复)key不一样
2)内部是红黑树,key-value键值对。
3)multiset不可用[]做insertion
4)c.insert(pair<long,string>(i,buff))
(*pItem).second
jj07.h
#pragma once
#include <iostream>
#include <map>
#include <ctime>
#include <string>
#include <stdexcept>
#include <cstdio>
#include <cstdlib>
using namespace std;
class jj07
{
public:
jj07();
~jj07();
void test_multimap(long&);
};
jj07.cpp
#include "jj07.h"
#include "Fzhs.h"
jj07::jj07()
{
}
void jj07::test_multimap(long& value)
{
Fzhs* f1 = new Fzhs;
cout << "\ntest_multimap()..........\n";
multimap<long, string> c;
char buf[10];
clock_t timeStart = clock();
for (long i = 0; i < value; ++i)
{
try
{
snprintf(buf, 10, "%d", rand());
//multimap 不可使用[] 做insertion
c.insert(pair<long, string>(i, buf));
}
catch (exception& p)
{
cout << "i = " << i << " " << p.what() << endl;
abort();
}
}
cout << "multi-seconds : " << (clock() - timeStart) << endl;
cout << "multimap.size() = " << c.size() << endl;
cout << "multimap.max_size() = " << c.max_size() << endl;
long target = f1->get_a_target_long();
timeStart = clock();
auto pItem = c.find(target);
cout << "c.find(), multi-seconds : " << (clock() - timeStart) << endl;
if (pItem != c.end())
cout << "found, value = " << (*pItem).second << endl;
else
cout << "not found!" << endl;
}
jj07::~jj07()
{
}
main.cpp
//以下测试程序之辅助函数
#include "jj01.h"
#include "jj02.h"
#include "jj03.h"
#include "jj04.h"
#include "jj05.h"
#include "jj17.h"
#include "jj18.h"
#include "jj06.h"
#include "jj07.h"
//使用容器array测试
int main()
{
jj07* j9 = new jj07;
long value;
cin >> value;
cout << "how many element : " << value << endl;
j9->test_multimap(value);
delete j9;
return 0;
}
结果
1000000
how many element : 1000000
test_multimap()..........
multi-seconds : 40679
multimap.size() = 1000000
multimap.max_size() = 89478485
target { 0~32767): 23456
c.find(), multi-seconds : 0
found, value = 9489
使用容器unordered_multiset——hash table
使用hashtable使用分离链地址方法实现
gnu C之前的名称hash_multiset
unorder_multiset.bucket_count篮子的个数
load_factor,max_load_factor,max_bucket_count方法
篮子后面的链表不能太长,元素的个数大于等于篮子的个数,就需要重新分配篮子的大小,重新进行插入元素
c.find()容器自身的find操作快很多
jj08.h
#pragma once
#include <unordered_set>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio> //snprintf()
#include <iostream>
#include <ctime>
using namespace std;
class jj08
{
public:
jj08();
~jj08();
void test_unordered_multiset(long&);
};
jj08.cpp
#include "jj08.h"
#include "Fzhs.h"
jj08::jj08()
{
}
void jj08::test_unordered_multiset(long& value)
{
Fzhs* f1 = new Fzhs;
cout << "\ntest_unordered_multiset()..........\n";
unordered_multiset<string> c;
char buf[10];
clock_t timeStart = clock();
for (long i = 0; i < value; ++i)
{
try
{
snprintf(buf, 10, "%d", rand());
c.insert(string(buf));
}
catch (exception& p)
{
cout << "i = " << i << " " << p.what() << endl;
abort();
}
}
cout << "milli-seconds : " << (clock() - timeStart) << endl;
cout << "unordered_multiset.size()= " << c.size() << endl;
cout << "unordered_multiset.max_size()= " << c.max_size() << endl; //357913941
cout << "unordered_multiset.bucket_count()= " << c.bucket_count() << endl;
cout << "unordered_multiset.load_factor()= " << c.load_factor() << endl;
cout << "unordered_multiset.max_load_factor()= " << c.max_load_factor() << endl;
cout << "unordered_multiset.max_bucket_count()= " << c.max_bucket_count() << endl;
for (unsigned i = 0; i < 20; ++i) {
cout << "bucket #" << i << " has " << c.bucket_size(i) << " elements.\n";
}
string target = f1->get_a_target_string();
{
timeStart = clock();
auto pItem = ::find(c.begin(), c.end(), target);
cout << "::find(), multi-swconds : " << (clock() - timeStart) << endl;
if (pItem != c.end())
cout << "found, " << *pItem << endl;
else
cout << "not found!" << endl;
}
}
jj08::~jj08()
{
}
main.cpp
//以下测试程序之辅助函数
#include "jj01.h"
#include "jj02.h"
#include "jj03.h"
#include "jj04.h"
#include "jj05.h"
#include "jj17.h"
#include "jj18.h"
#include "jj06.h"
#include "jj07.h"
#include "jj08.h"
//使用容器array测试
int main()
{
jj08* j10 = new jj08;
long value;
cin >> value;
cout << "how many element : " << value << endl;
j10->test_unordered_multiset(value);
delete j10;
return 0;
}
结果
1000000
how many element : 1000000
test_unordered_multiset()..........
milli-seconds : 33848
unordered_multiset.size()= 1000000
unordered_multiset.max_size()= 119304647
unordered_multiset.bucket_count()= 1048576
unordered_multiset.load_factor()= 0.953674
unordered_multiset.max_load_factor()= 1
unordered_multiset.max_bucket_count()= 536870911
bucket #0 has 0 elements.
bucket #1 has 0 elements.
bucket #2 has 0 elements.
bucket #3 has 0 elements.
bucket #4 has 0 elements.
bucket #5 has 0 elements.
bucket #6 has 0 elements.
bucket #7 has 0 elements.
bucket #8 has 0 elements.
bucket #9 has 0 elements.
bucket #10 has 0 elements.
bucket #11 has 0 elements.
bucket #12 has 0 elements.
bucket #13 has 0 elements.
bucket #14 has 0 elements.
bucket #15 has 0 elements.
bucket #16 has 0 elements.
bucket #17 has 0 elements.
bucket #18 has 0 elements.
bucket #19 has 0 elements.
target { 0~32767): 23456
::find(), multi-swconds : 439
found, 23456
c.find(), milti-seconds : 0
found, 23456
使用容器unordered_multimap
这个好理解。无序容器的内部是由一个个的bucket(桶)构成的,
每个bucket里面由相同hash的元素构成。
因此无序容器的搜索是先根据hash值,定位到bucket,然后再在bucket里面搜索符合条件的元素。
buck_count - 就是无序容器内部bucket的数量;
size - 无序容器中总的元素数量;
max_load_factor - 就是bucket所容纳的最大平均元素的数量(可以是分数值)。
『例如』:如果一个容器中有100个元素,容器中bucket的最大平均元素值是12.5,那么需要多少个桶才能完全装下这100个元素呢? 100/12.5 = 8, 为确保有足够的桶,bucket数量起码是>8(即最少9个)。
jj09.h
#pragma once
#include <unordered_map>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio> //snprintf()
#include <iostream>
#include <ctime>
class jj09
{
public:
jj09();
~jj09();
void test_unordered_multimap(long&);
};
jj09.cpp
#include "jj09.h"
#include "Fzhs.h"
jj09::jj09()
{
}
void jj09::test_unordered_multimap(long& value)
{
Fzhs* f1 = new Fzhs;
cout << "\ntest_unordered_multimap()..........\n";
unordered_map<long, string> c;
char buf[10];
clock_t timeStart = clock();
for (long i = 0; i < value; ++i)
{
try
{
snprintf(buf, 10, "%d", rand());
//multimap 不可用[] 进行 insertion
c.insert(pair<long, string>(i, buf));
}
catch (exception& p)
{
cout << "i - " << " " << p.what() << endl;
abort();
}
}
cout << "milli-seconds : " << (clock() - timeStart) << endl;
cout << "unordered_multimap.size()= " << c.size() << endl;
cout << "unordered_multimap.max_size()= " << c.max_size() << endl; //357913941
long target = f1->get_a_target_long();
timeStart = clock();
auto pItem = c.find(target);
cout << "c.find(), multi-seconds : " << (clock() - timeStart) << endl;
if (pItem != c.end())
cout << "found, value = " << (*pItem).second << endl;
else
cout << "not found!" << endl;
}
jj09::~jj09()
{
}
main.cpp
//以下测试程序之辅助函数
#include "jj01.h"
#include "jj02.h"
#include "jj03.h"
#include "jj04.h"
#include "jj05.h"
#include "jj17.h"
#include "jj18.h"
#include "jj06.h"
#include "jj07.h"
#include "jj08.h"
#include "jj09.h"
//使用容器array测试
int main()
{
jj09* j11 = new jj09;
long value;
cin >> value;
cout << "how many element : " << value << endl;
j11->test_unordered_multimap(value);
delete j11;
return 0;
}
结果
1000000
how many element : 1000000
test_unordered_multimap()..........
milli-seconds : 41456
unordered_multimap.size()= 1000000
unordered_multimap.max_size()= 107374182
target { 0~32767): 23456
c.find(), multi-seconds : 0
found, value = 9489
使用容器set
1、不允许重复,key独一无二
2、key= value
3、随机数是在0-32767,因为不允许重复,所以最多只能放32768个元素
jj13.h
#pragma once
#include <set>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio> //snprintf()
#include <iostream>
#include <ctime>
using namespace std;
class jj13
{
public:
jj13();
~jj13();
void test_set(long&);
};
jj13.cpp
#include "jj13.h"
#include "Fzhs.h"
jj13::jj13()
{
}
void jj13::test_set(long& value)
{
Fzhs* f1 = new Fzhs;
cout << "\ntest_set()........\n";
set<string> c;
char buf[10];
clock_t timeStart = clock();
for (long i = 0; i < value; ++i)
{
try
{
snprintf(buf, 10, "%d", rand());
c.insert(string(buf));
}
catch (exception& p)
{
cout << "i = " << " " << p.what() << endl;
abort();
}
}
cout << "milli-seconds : " << (clock() - timeStart) << endl;
cout << "set.size()= " << c.size() << endl;
cout << "set.max_size()= " << c.max_size() << endl; //214748364
string target = f1->get_a_target_string();
{
timeStart = clock();
auto pItem = ::find(c.begin(), c.end(), target);
cout << "::find(), milti-seconds : " << (clock() - timeStart) << endl;
if (pItem != c.end())
cout << "found, " << *pItem << endl;
else
cout << "not found!" << endl;
}
{
timeStart = clock();
auto pItem = c.find(target);
cout << "c.find(), milti-seconds : " << (clock() - timeStart) << endl;
if (pItem != c.end())
cout << "found, " << *pItem << endl;
else
cout << "not found!" << endl;
}
}
jj13::~jj13()
{
}
main.cpp
//以下测试程序之辅助函数
#include "jj01.h"
#include "jj02.h"
#include "jj03.h"
#include "jj04.h"
#include "jj05.h"
#include "jj17.h"
#include "jj18.h"
#include "jj06.h"
#include "jj07.h"
#include "jj08.h"
#include "jj09.h"
#include "jj13.h"
//使用容器set测试
int main()
{
jj13* j12 = new jj13;
long value;
cin >> value;
cout << "how many element : " << value << endl;
j12->test_set(value);
delete j12;
return 0;
}
结果
1000000
how many element : 1000000
test_set()........
milli-seconds : 29899
set.size()= 32768
set.max_size()= 97612893
target { 0~32767): 23456
::find(), milti-seconds : 11
found, 23456
c.find(), milti-seconds : 0
found, 23456
使用容器map
jj14.h
#pragma once
#include <map>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio> //snprintf()
#include <iostream>
#include <ctime>
using namespace std;
class jj14
{
public:
jj14();
~jj14();
void test_map(long& value);
};
jj14.cpp
#include "jj14.h"
#include "Fzhs.h"
jj14::jj14()
{
}
void jj14::test_map(long& value)
{
Fzhs* f1 = new Fzhs;
cout << "\ntest_map()..........\n";
map<long, string> c;
char buf[10];
clock_t timeStart = clock();
for (long i = 0; i < value; ++i)
{
try {
snprintf(buf, 10, "%d", rand());
c[i] = string(buf); //key不一样 value有可能一样,这个key = i, value = buf
}
catch (exception& p) {
cout << "i=" << i << " " << p.what() << endl;
abort();
}
}
cout << "milli-seconds : " << (clock() - timeStart) << endl;
cout << "map.size()= " << c.size() << endl;
cout << "map.max_size()= " << c.max_size() << endl; //178956970
long target = f1->get_a_target_long();
timeStart = clock();
auto pItem = c.find(target);
cout << "c.find(), milli-seconds : " << (clock() - timeStart) << endl;
if (pItem != c.end())
cout << "found, value=" << (*pItem).second << endl;
else
cout << "not found! " << endl;
c.clear();
}
jj14::~jj14()
{
}
main.cpp
//以下测试程序之辅助函数
#include "jj01.h"
#include "jj02.h"
#include "jj03.h"
#include "jj04.h"
#include "jj05.h"
#include "jj17.h"
#include "jj18.h"
#include "jj06.h"
#include "jj07.h"
#include "jj08.h"
#include "jj09.h"
#include "jj13.h"
#include "jj14.h"
int main()
{
jj14* j13 = new jj14;
long value;
cin >> value;
cout << "how many element : " << value << endl;
j13->test_map(value);
delete j13;
return 0;
}
结果
1000000
how many element : 1000000
test_map()..........
milli-seconds : 34608
map.size()= 1000000
map.max_size()= 89478485
target { 0~32767): 23456
c.find(), milli-seconds : 0
found, value=9489
使用容器unordered_set
jj15.h
#pragma once
#include <unordered_set>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio> //snprintf()
#include <iostream>
#include <ctime>
using namespace std;
class jj15
{
public:
jj15();
~jj15();
void test_unordered_set(long&);
};
jj15.cpp
#include "jj15.h"
#include "Fzhs.h"
jj15::jj15()
{
}
void jj15::test_unordered_set(long& value)
{
Fzhs* f1 = new Fzhs;
cout << "\ntest_unordered_set().......... \n";
unordered_set<string> c;
char buf[10];
clock_t timeStart = clock();
for (long i = 0; i < value; ++i)
{
try {
snprintf(buf, 10, "%d", rand());
c.insert(string(buf));
}
catch (exception& p) {
cout << "i=" << i << " " << p.what() << endl;
abort();
}
}
cout << "milli-seconds : " << (clock() - timeStart) << endl;
cout << "unordered_set.size()= " << c.size() << endl;
cout << "unordered_set.max_size()= " << c.max_size() << endl; //357913941
cout << "unordered_set.bucket_count()= " << c.bucket_count() << endl;
cout << "unordered_set.load_factor()= " << c.load_factor() << endl;
cout << "unordered_set.max_load_factor()= " << c.max_load_factor() << endl;
cout << "unordered_set.max_bucket_count()= " << c.max_bucket_count() << endl;
for (unsigned i = 0; i < 20; ++i) {
cout << "bucket #" << i << " has " << c.bucket_size(i) << " elements.\n";
}
string target = f1->get_a_target_string();
{
timeStart = clock();
auto pItem = find(c.begin(), c.end(), target); //比 c.find(...) 慢很多
cout << "std::find(), milli-seconds : " << (clock() - timeStart) << endl;
if (pItem != c.end())
cout << "found, " << *pItem << endl;
else
cout << "not found! " << endl;
}
{
timeStart = clock();
auto pItem = c.find(target); //比 std::find(...) 快很多
cout << "c.find(), milli-seconds : " << (clock() - timeStart) << endl;
if (pItem != c.end())
cout << "found, " << *pItem << endl;
else
cout << "not found! " << endl;
}
}
jj15::~jj15()
{
}
main.cpp
//以下测试程序之辅助函数
#include "jj01.h"
#include "jj02.h"
#include "jj03.h"
#include "jj04.h"
#include "jj05.h"
#include "jj17.h"
#include "jj18.h"
#include "jj06.h"
#include "jj07.h"
#include "jj08.h"
#include "jj09.h"
#include "jj13.h"
#include "jj14.h"
#include "jj15.h"
int main()
{
jj15* j14 = new jj15;
long value;
cin >> value;
cout << "how many element : " << value << endl;
j14->test_unordered_set(value);
delete j14;
return 0;
}
结果
1000000
how many element : 1000000
test_unordered_set()..........
milli-seconds : 16244
unordered_set.size()= 32768
unordered_set.max_size()= 119304647
unordered_set.bucket_count()= 32768
unordered_set.load_factor()= 1
unordered_set.max_load_factor()= 1
unordered_set.max_bucket_count()= 536870911
bucket #0 has 1 elements.
bucket #1 has 0 elements.
bucket #2 has 2 elements.
bucket #3 has 0 elements.
bucket #4 has 3 elements.
bucket #5 has 3 elements.
bucket #6 has 1 elements.
bucket #7 has 0 elements.
bucket #8 has 0 elements.
bucket #9 has 1 elements.
bucket #10 has 0 elements.
bucket #11 has 1 elements.
bucket #12 has 1 elements.
bucket #13 has 1 elements.
bucket #14 has 0 elements.
bucket #15 has 0 elements.
bucket #16 has 0 elements.
bucket #17 has 0 elements.
bucket #18 has 0 elements.
bucket #19 has 0 elements.
target { 0~32767): 23456
std::find(), milli-seconds : 24
found, 23456
c.find(), milli-seconds : 0
found, 23456
使用容器unordered_map
jj16.h
#pragma once
#include <unordered_map>
#include <stdexcept>
#include <string>
#include <cstdlib> //abort()
#include <cstdio> //snprintf()
#include <iostream>
#include <ctime>
using namespace std;
class jj16
{
public:
jj16();
~jj16();
void test_unordered_map(long&);
};
jj16.cpp
#include "jj16.h"
#include "Fzhs.h"
jj16::jj16()
{
}
void jj16::test_unordered_map(long& value)
{
Fzhs* f1 = new Fzhs;
cout << "\ntest_unordered_map().......... \n";
unordered_map<long, string> c;
char buf[10];
clock_t timeStart = clock();
for (long i = 0; i < value; ++i)
{
try {
snprintf(buf, 10, "%d", rand());
c[i] = string(buf);
}
catch (exception& p) {
cout << "i=" << i << " " << p.what() << endl;
abort();
}
}
cout << "milli-seconds : " << (clock() - timeStart) << endl;
cout << "unordered_map.size()= " << c.size() << endl; //357913941
cout << "unordered_map.max_size()= " << c.max_size() << endl;
long target = f1->get_a_target_long();
timeStart = clock();
//! auto pItem = find(c.begin(), c.end(), target); //map 不適用 std::find()
auto pItem = c.find(target);
cout << "c.find(), milli-seconds : " << (clock() - timeStart) << endl;
if (pItem != c.end())
cout << "found, value=" << (*pItem).second << endl;
else
cout << "not found! " << endl;
}
jj16::~jj16()
{
}
main.cpp
//以下测试程序之辅助函数
#include "jj01.h"
#include "jj02.h"
#include "jj03.h"
#include "jj04.h"
#include "jj05.h"
#include "jj17.h"
#include "jj18.h"
#include "jj06.h"
#include "jj07.h"
#include "jj08.h"
#include "jj09.h"
#include "jj13.h"
#include "jj14.h"
#include "jj15.h"
#include "jj16.h"
int main()
{
jj16* j15 = new jj16;
long value;
cin >> value;
cout << "how many element : " << value << endl;
j15->test_unordered_map(value);
delete j15;
return 0;
}
结果
1000000
how many element : 1000000
test_unordered_map()..........
milli-seconds : 95618
unordered_map.size()= 1000000
unordered_map.max_size()= 107374182
target { 0~32767): 2345
c.find(), milli-seconds : 0
found, value=20274