索引、哈希表、跳跃表
2015-09-14 11:25
218 查看
索引(maps)、哈希表和跳跃表
*Maps
一个索引存储元素号他们能够很快用键值找到这些对应元素。搜索除了这些有用的信息他自己的键值的元素。但是这个方式将要得道信息用来搜索关键值。特别的是,一个map将要存储一个键值对(k,v),我们将要调用所有,k是一个关键值并且v是相对应的值。除此之外,这个map抽象数据类型有要求每个键值是唯一的,这里将要定义键值和值定义一个map。为了完成这个高效率的普遍性,我们允许这个关键值和值存储在这个map有任何的对象类型。这个map将要存储一个student记录(包括有student's 名字、地址以及课程)
这个值可能是兄生的ID号。一些应用,这个关键值和值可能是相同的。例如,如果我们有个map来存储这些数字。我们能够用每个数字作为关键字和值。
事实上,我们用这个关键值作为唯一的锁定并且分配这个应用或者是用户分配一个值对象。
*条目和组合模式
作为上面说的,一个map将要存储一堆键值。事实上有更多的产生大量的面向对象设计模式,这个模型的位置,定义一个单一对象来组成其他的对象。这是个最简单的方式,
因为他将要合并两个对象到单一的对象中。
解释这个概念,我们将要定义这个类存储两个对象在第一个和第二个成员变量,并且提供这些功能。在下面代码,我们将要解释存储这个键值对类型。这有个结构,他将要提供这个成员功能来返回一个键值对。他也能要提供这个功能来允许我们设置这个键值对成员。
template <typename k,typename V>
class Entry{
public:
Entry(const K&k = K(),const V& v= V()):_key(k),_value(v){}
const K& key() const {return _key;}
const V& value() const {return _value;}
void setKey(const K&k){_key = k;}
void setValue(const V& v){_value = v;}
private:
K _key;
V _value;
};
*Map抽象数据类型
在这节,我们来描述一个map抽象数据,调用这个MAP来完成键值,每个值都要联系区分一个关键值。我们要假设这个map要提供这个特别指向的对象,来允许我们提供一个map。
为了支持c++模板类库,我们定义这个更多的公共对象来调用iterator,给定这个map迭代器p,非关联化的东西都由迭代器来访问。这些独立的键值可以用p->ley()或者是
p->value。对于这些迭代器来自它现在的位置,我们将要重载这些加加操作。因此,++p这个迭代器p将要指向下个map。我们能够列举这些map并且初始化M.begin来p++
只要它不等于M.end();
为了指出这个对象不在map中,我们能够假设这个存在的特别的迭代器称为end。map抽象数据支持:
size();
返回一个M数字。
empty();
返回一个true如果M为空,否则为false;
find(k);
如果m包括了e = (k,v),这个值等于k,然后返回一个迭代器p提供给这个条目,否则返回一个特别的迭代器end。
put(k,v):
如果m没有一个键值条目等于k,那么增加这个(k,v)到m,
erase(k):
移除这个m这些关键值等于了k;一个错误情况造成如果m没有条目。
erase(p):
移除来自于m通过这个p,这里有个错误场景如果p指向end。
begin();
返回迭代器的条目m的第一个。
end();
返回一个迭代器位置end();
下面,我们将要展示这些操作的影响。
操作 输出 Map
empty() true 0
put(5,A) p1:[(5,A)] {(5,A)}
put(7,B) p2:[(7.B)] {(5,A),(7,B)}
put(2,C) p3:[(2,C)] {(5,A),(7,B),(2,C)}
put(2,E) p3:[(2,E)] {(5,A),(7,B),(2,E)}
find(7) p2:[(7,B)] {(5,A),(7,B),(2,E)}
find(4) end {(5,A),(7,B),(2,E)}
find(2) p3:[(2,E)] {(5,A),(7,B),(2,E)}
size() 3 {(5,A),(7,B),(2,E)}
erase(5) - {(7,B),(2,E)}
erase(p3) - {(7,B)}
*C++Map的接口
现在让我们讨论这个map数据结构,我们首先定义这个c++接口对于map代码,它并不是一个完全的c++类,这里仅仅是一个公共功能的声明。这个借口是一个模板有两个
类型,这个关键值类型K和值类型V。
template <typename K,typename V>
class Map{
public:
class Entry;
class Iterator;
int size() const;
bool empty() const;
Iterator find(const K& k) const;
Iterator put(const K& k,const V& v);
void erase(const K& k)
throw(NonexistentElement);
void erase(const Iterator& p);
Iterator begin();
Iterator end();
};
除了这些成员功能,这个接口有定义两个类型,条目和迭代器。这两个类有提供这些类型和迭代器对象。在这个类外,可以通过Map<K,V>::Entry 和 Map<K,V>::Iterator,/
我们并没有表现一个迭代器对象,这个有定义一个简单的STL迭代器,他将要支持“*”,并且返回一个所联系的条目。用“++”或者“--”来移动这个迭代器。这两个迭代器能够
通过用“==”来比较。
这里有很多聪明的实现提供三个类型,命名一个“const”迭代器。比如iterator提供一个读条目的功能而不是改变他们。我们将要发出这个类型为了保持我们借口有简洁
的联系。这个剩余的接口允许我们来描述这些map操作。一个错误的情况将要造成功能erase(k)来通过K来调用并不是这个Map.这里也有个信号来抛出类型一场。他要定义一个
简单的异常作为我们所看到的。
*STL map类
这个C++标准类库提供一个map阐述来调用map.这有大量的stl模板我们所看到的,这个stl map是其中一个容器例子,他将要支持迭代器。
为了声明这个对象类型map,他是有必要的包括定义这个文件来调用“map”。这个“map”是std命名空间,并且因此他是必要的用一个“std::map”或者是提供这个“using”状态
STLmap是一个模板并且他有两个参数,这个键类型和这个值类型。作为这个STL容器,一个迭代器类型将要提供这个条目并且列举这些符合条目。这个map迭代器类型是
map<K,E>::iterator。(k,v)要存储这个对象。给定一个迭代器p,他将要联系这个键值对象并且能够用到P->first和p->second.每个Map对象M有定义两个,这些功能是
begin和end();在这里m.begin产出这个迭代器第一个元素,并且m.end将要产出这个迭代器最后元素。这将要以为着我们移动从开始到最后通过用map增加或者减少。
这个stlmap原理是。让M声明是一个STLmap,让k是一个键值对象,并且v是一个对象值对于类m。让P声明为m的一个迭代器。
size()/empty()/find(k)/operator[k]:/insert(pair(k,v)):/erase(k):/begin():/end():/
map抽象数据类型是相当简单对于上述功能,搜索,查找并且改变这个条目。给定一个map M,分配“M[k] = v”插入这个键值对(k,v),来改变这个值。相似于我们的抽象
数据类型put(k,v)。读这个值M【k】相当于find(k)。
map<string,int> mymap;
map<string,int>::iterator p;
mymap.insert(pair<string,int>)("Rob",28)
mymap["Joe"] = 38;
mymap["Joe"] = 50;
mymap["Sue"] = 75;
p = mymap.find("Joe");
mymap.erase(p);
mymap.erase("Sue");
p = mymap.find("Joe");
if(p == mymap.end())
for(p = mymap.begin();p != mymap.end();++p)
{
cout<<//////;
}
作为stl容器,他并不能检测错误。
*简单的链表基于map结构
这里有简单的方式来解释map存储在链表里他的N为条目在l链表中,补充作为双向链表。表现一个基本的功能,find(k),put(k,v)还有erase(k)。
Algorithm find(k):
Input: A key k
Output:
for each position p∈[L.begin(),L.end()]do
if p.key() = k then
return p
return end //there is no entry with key equal to k
Algorithm put(k,v)
Input:A key-value pair(k,v)
OUtput://///
for each position p∈[L.begin(),L.end()]do
if p.key() = k then
*p-> (k,v)
return p
p <- L.insertBack((k,v))
n <- n+1
return p
Algorithm erase(k):
Input: A key k
Output: None
for each position p ∈ [L.begin(),L.end()) do
if p.key() = k then
L.erase(p)
n ← n − 1 {decrement variable storing number of entries}
这给出了个简单模式,他有效率并且是一个小map。这个基本功能花费一个O(n)时间,因为每个函数将要去列表中查找这是最坏的事情。因此,我们想要做的更快更好。
*Maps
一个索引存储元素号他们能够很快用键值找到这些对应元素。搜索除了这些有用的信息他自己的键值的元素。但是这个方式将要得道信息用来搜索关键值。特别的是,一个map将要存储一个键值对(k,v),我们将要调用所有,k是一个关键值并且v是相对应的值。除此之外,这个map抽象数据类型有要求每个键值是唯一的,这里将要定义键值和值定义一个map。为了完成这个高效率的普遍性,我们允许这个关键值和值存储在这个map有任何的对象类型。这个map将要存储一个student记录(包括有student's 名字、地址以及课程)
这个值可能是兄生的ID号。一些应用,这个关键值和值可能是相同的。例如,如果我们有个map来存储这些数字。我们能够用每个数字作为关键字和值。
事实上,我们用这个关键值作为唯一的锁定并且分配这个应用或者是用户分配一个值对象。
*条目和组合模式
作为上面说的,一个map将要存储一堆键值。事实上有更多的产生大量的面向对象设计模式,这个模型的位置,定义一个单一对象来组成其他的对象。这是个最简单的方式,
因为他将要合并两个对象到单一的对象中。
解释这个概念,我们将要定义这个类存储两个对象在第一个和第二个成员变量,并且提供这些功能。在下面代码,我们将要解释存储这个键值对类型。这有个结构,他将要提供这个成员功能来返回一个键值对。他也能要提供这个功能来允许我们设置这个键值对成员。
template <typename k,typename V>
class Entry{
public:
Entry(const K&k = K(),const V& v= V()):_key(k),_value(v){}
const K& key() const {return _key;}
const V& value() const {return _value;}
void setKey(const K&k){_key = k;}
void setValue(const V& v){_value = v;}
private:
K _key;
V _value;
};
*Map抽象数据类型
在这节,我们来描述一个map抽象数据,调用这个MAP来完成键值,每个值都要联系区分一个关键值。我们要假设这个map要提供这个特别指向的对象,来允许我们提供一个map。
为了支持c++模板类库,我们定义这个更多的公共对象来调用iterator,给定这个map迭代器p,非关联化的东西都由迭代器来访问。这些独立的键值可以用p->ley()或者是
p->value。对于这些迭代器来自它现在的位置,我们将要重载这些加加操作。因此,++p这个迭代器p将要指向下个map。我们能够列举这些map并且初始化M.begin来p++
只要它不等于M.end();
为了指出这个对象不在map中,我们能够假设这个存在的特别的迭代器称为end。map抽象数据支持:
size();
返回一个M数字。
empty();
返回一个true如果M为空,否则为false;
find(k);
如果m包括了e = (k,v),这个值等于k,然后返回一个迭代器p提供给这个条目,否则返回一个特别的迭代器end。
put(k,v):
如果m没有一个键值条目等于k,那么增加这个(k,v)到m,
erase(k):
移除这个m这些关键值等于了k;一个错误情况造成如果m没有条目。
erase(p):
移除来自于m通过这个p,这里有个错误场景如果p指向end。
begin();
返回迭代器的条目m的第一个。
end();
返回一个迭代器位置end();
下面,我们将要展示这些操作的影响。
操作 输出 Map
empty() true 0
put(5,A) p1:[(5,A)] {(5,A)}
put(7,B) p2:[(7.B)] {(5,A),(7,B)}
put(2,C) p3:[(2,C)] {(5,A),(7,B),(2,C)}
put(2,E) p3:[(2,E)] {(5,A),(7,B),(2,E)}
find(7) p2:[(7,B)] {(5,A),(7,B),(2,E)}
find(4) end {(5,A),(7,B),(2,E)}
find(2) p3:[(2,E)] {(5,A),(7,B),(2,E)}
size() 3 {(5,A),(7,B),(2,E)}
erase(5) - {(7,B),(2,E)}
erase(p3) - {(7,B)}
*C++Map的接口
现在让我们讨论这个map数据结构,我们首先定义这个c++接口对于map代码,它并不是一个完全的c++类,这里仅仅是一个公共功能的声明。这个借口是一个模板有两个
类型,这个关键值类型K和值类型V。
template <typename K,typename V>
class Map{
public:
class Entry;
class Iterator;
int size() const;
bool empty() const;
Iterator find(const K& k) const;
Iterator put(const K& k,const V& v);
void erase(const K& k)
throw(NonexistentElement);
void erase(const Iterator& p);
Iterator begin();
Iterator end();
};
除了这些成员功能,这个接口有定义两个类型,条目和迭代器。这两个类有提供这些类型和迭代器对象。在这个类外,可以通过Map<K,V>::Entry 和 Map<K,V>::Iterator,/
我们并没有表现一个迭代器对象,这个有定义一个简单的STL迭代器,他将要支持“*”,并且返回一个所联系的条目。用“++”或者“--”来移动这个迭代器。这两个迭代器能够
通过用“==”来比较。
这里有很多聪明的实现提供三个类型,命名一个“const”迭代器。比如iterator提供一个读条目的功能而不是改变他们。我们将要发出这个类型为了保持我们借口有简洁
的联系。这个剩余的接口允许我们来描述这些map操作。一个错误的情况将要造成功能erase(k)来通过K来调用并不是这个Map.这里也有个信号来抛出类型一场。他要定义一个
简单的异常作为我们所看到的。
*STL map类
这个C++标准类库提供一个map阐述来调用map.这有大量的stl模板我们所看到的,这个stl map是其中一个容器例子,他将要支持迭代器。
为了声明这个对象类型map,他是有必要的包括定义这个文件来调用“map”。这个“map”是std命名空间,并且因此他是必要的用一个“std::map”或者是提供这个“using”状态
STLmap是一个模板并且他有两个参数,这个键类型和这个值类型。作为这个STL容器,一个迭代器类型将要提供这个条目并且列举这些符合条目。这个map迭代器类型是
map<K,E>::iterator。(k,v)要存储这个对象。给定一个迭代器p,他将要联系这个键值对象并且能够用到P->first和p->second.每个Map对象M有定义两个,这些功能是
begin和end();在这里m.begin产出这个迭代器第一个元素,并且m.end将要产出这个迭代器最后元素。这将要以为着我们移动从开始到最后通过用map增加或者减少。
这个stlmap原理是。让M声明是一个STLmap,让k是一个键值对象,并且v是一个对象值对于类m。让P声明为m的一个迭代器。
size()/empty()/find(k)/operator[k]:/insert(pair(k,v)):/erase(k):/begin():/end():/
map抽象数据类型是相当简单对于上述功能,搜索,查找并且改变这个条目。给定一个map M,分配“M[k] = v”插入这个键值对(k,v),来改变这个值。相似于我们的抽象
数据类型put(k,v)。读这个值M【k】相当于find(k)。
map<string,int> mymap;
map<string,int>::iterator p;
mymap.insert(pair<string,int>)("Rob",28)
mymap["Joe"] = 38;
mymap["Joe"] = 50;
mymap["Sue"] = 75;
p = mymap.find("Joe");
mymap.erase(p);
mymap.erase("Sue");
p = mymap.find("Joe");
if(p == mymap.end())
for(p = mymap.begin();p != mymap.end();++p)
{
cout<<//////;
}
作为stl容器,他并不能检测错误。
*简单的链表基于map结构
这里有简单的方式来解释map存储在链表里他的N为条目在l链表中,补充作为双向链表。表现一个基本的功能,find(k),put(k,v)还有erase(k)。
Algorithm find(k):
Input: A key k
Output:
for each position p∈[L.begin(),L.end()]do
if p.key() = k then
return p
return end //there is no entry with key equal to k
Algorithm put(k,v)
Input:A key-value pair(k,v)
OUtput://///
for each position p∈[L.begin(),L.end()]do
if p.key() = k then
*p-> (k,v)
return p
p <- L.insertBack((k,v))
n <- n+1
return p
Algorithm erase(k):
Input: A key k
Output: None
for each position p ∈ [L.begin(),L.end()) do
if p.key() = k then
L.erase(p)
n ← n − 1 {decrement variable storing number of entries}
这给出了个简单模式,他有效率并且是一个小map。这个基本功能花费一个O(n)时间,因为每个函数将要去列表中查找这是最坏的事情。因此,我们想要做的更快更好。
相关文章推荐
- fileinput模块
- javscript WINDOW 浏览器对象模型
- 华为OJ平台题目:(练习用)挑7
- nodejs+express的简单示例
- ACID属性区别
- 计算集合的并集、交集、差集
- AppCan插件开发学习
- 解决mysql数据库大小写敏感问题【mysql数据库和表其实是数据目录下的目录和文件,所以操作系统的敏感性决定数据库和表命名的大小写敏感】
- android studio注意要点及常见错误
- hdu5441(2015长春网络赛E题)
- android弹出软键盘时,editText被遮挡的问题
- 分析 shell 中 的 复杂的 && 和 || 表达式
- 小议:如何用PowerShell Remove-SPOWeb?
- 数字电视CA反授权
- aircrack加reaver破解带有wps的wifi
- iis下设置默认页
- 防止过拟合的几个方法
- 部分算法
- proc文件系统API
- Teradata join 优化