7.[数据结构和算法分析笔记]词典 Dictionary

简介:

1.词典 Dictionary

定义

词典,也称映射(map),表(table)或关联胡祖(associatearray),词典中每个元素都由两部分组成:一个关键字,通常称为查找键(search key);一个与该键值相关联的值。

词典根据查找键来组织与区分它的元素,因此只要指定元素的查找键,就能从词典中检索或删除一个元素。词典中每个元素都具有一个查找键,虽然也可以将具有查找键的元素放入线性表,但线性表的数据是按位置而不是按查找键来组织的。

Java接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public  interface  DictionaryInterface<K, V> {
     /**
      * 将一个新元素插入词典。如果给定的查找键一再词典中,则替换相应的值
      * @param key 新元素的查找键对象
      * @param value 与查找键相关联的对象
      * @return 如果新元素被插入到词典中则返回null,如果与key相关联的值被替换,则返回原来的值 */
     public  V add(K key, V value);
     /**
      * 从词典中删除一个指定的元素
      * @param key 欲删除的元素的查找键对象
      * @return 与查找键相关联的值,如果不存在这样的对象则返回null */
     public  V remove(K key);
     /**
      * 检索与给定的查找键相关联的对值
      * @param key 欲检索的元素的查找键对象
      * @return 与查找键相关联的值,如果不存在这样的对象则返回null */
     public  V getValue(K key);
     /**
      * 确定一个指定的元素在不在词典中
      * @param key 欲检索的元素的查找键对象
      * @return 如果key与词典中的一个元素相关联则返回true */
     public  boolean  contains(K key);
     /**
      * 创建一个迭代器遍历词典中所有的查找键
      * @return 返回一个迭代器,提供对词典中查找键的顺序访问 */
     public  Iterator<K> getKeyIterator();
     /**
      * 创建一个迭代器遍历词典中所有的值
      * @return 返回一个迭代器,提供对词典中的值顺序访问 */
     public  Iterator<V> getValueIterator();
     /**
      * 确定词典是否为空
      * @return 如果词典为空则返回true */
     public  boolean  isEmpty();
     /**
      * 确定词典是否为满
      * @return 如果词典为满则返回true */
     public  boolean  isFull();
     /**
      * 缺德词典的大小
      * @return 返回词典中当前的元素(键-值二元组)数目 */
     public  int  getSize();
     /**
      * 删除词典中所有元素 */
     public  void  clear();
}

Java类库:Map接口

1
2
3
4
5
6
7
8
9
10
11
12
13
public  interface  Map<K, V> {
     public  V put(K key, V value);
     public  V remove(Object key);
     public  V get(Object key);
     public  boolean  containsKey(Object key);
     public  boolean  containsValue(Object value);
     public  Set keySet();
     public  Collection<V> values();
     public  boolean  isEmpty();
     public  int  size();
     public  void  clear();
                                
}


2.迭代器 Iterator

迭代器总是指向链表中的一些链接点。它同链表相关联,但并不等同于链表或链接点。

150301989.png

迭代器类

迭代器类包含对数据结构中数据项的引用,并用来遍历这些结构的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
public  class  Link {
     public  long  dData;
     public  Link next;
}
public  class  LinkList {
     private  Link first;
     public  ListIterator getIterator() {
         return  new  ListIterator( this );
     }
}
public  class  ListIterator {
     private  Link current;  // reference to current link
     private  Link previous;  // reference to previous link
     private  LinkList ourList;  // reference to "parent" list
     public  ListIterator(LinkList list) {
         ourList = list;
         reset();
     }
     // 把迭代器复位并设在表头
     public  void  reset() {
         current = ourList.getFirst();
         previous =  null ;
     }
     public  boolean  atEnd() {
         return  (current.next ==  null );
     }
     public  void  nextLink() {
         previous = current;
         current = current.next;
     }
     public  Link getCurrent() {
         return  current;
     }
     // 在当前链接点前插入新连接点
     public  void  insertAfter() {
         Link newLink =  new  Link();
         if  (ourList.isEmpty()) {
             ourList.setFirst(newLink);
             current = newLink;
         else  {
             newLink.next = current.next;
             current.next = newLink;
             nextLink();
         }
     }
     // 在当前链接点后插入新连接点
     public  void  insertBefor() {
         Link newLink =  new  Link();
         if  (previous ==  null ) {
             newLink.next = ourList.getFirst();
             ourList.setFirst(newLink);
             reset();
         else  {
             newLink.next = previous.next;
             previous.next = newLink;
             current = newLink;
         }
     }
     // 删除当前链接点
     public  long  deleteCurrent() {
         long  value = current.dData;
         if  (previous ==  null ) {
             ourList.setFirst(current.next);
             reset();
         else  {
             previous.next = current.next;
             if  (atEnd())
                 reset();
             else
                 current = current.next;
         }
         return  value;
     }
}

3.基于数组实现词典

词典中的每个元素必须是Entry类的一个实例。

150315574.png

基于数组的无序词典

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
public  class  ArrayDictionary<K, V>  implements  DictionaryInterface<K, V>,
         Serializable {
     private  Entry<K, V>[] dictionary;  // 无需元素的数组
     private  int  currentSize;  // 元素的数量
     private  final  static  int  DEFAULT_CAPACITY =  25 ;
     public  ArrayDictionary() {
         this (DEFAULT_CAPACITY);
     }
     public  ArrayDictionary( int  initialCapacity) {
         // 编译器发现,含有Entry类型的元素的数组赋给了含有Entry<K,V>类型的元素的数组。因此,它警告有一个未检验的转换。
         // 试图把新数值转换为Entry<K,V>也将导致一个类似的警告。
         // 这两种情况都不用编译器的警告。
         dictionary =  new  Entry[initialCapacity];
         currentSize =  0 ;
     }
     private  class  Entry<S, T>  implements  Serializable {
         private  S key;
         private  T value;
         private  Entry(S searchKey, T dataValue) {
             key = searchKey;
             value = dataValue;
         }
         // 内部Entry不具有用于设置或修改查找键的方法setKey
         public  S getKey() {
             return  key;
         }
         public  T getValue() {
             return  value;
         }
         public  void  setValue(T value) {
             this .value = value;
         }
     }
     public  V add(K key, V value) {
         // 讲一个新的键-值元素插入词典并返回null。如果key已在词典中,则返回相应的值,并且用value替换它
         V result =  null ;
         // 在数值中查找含有key的元素
         int  keyIndex = locateIndex(key);
         // 如果在数组中找到含有key的元素
         if (keyIndex < currentSize) {
             // result = 当前与key相关联的值
             result = dictionary[keyIndex].getValue();
             // 以value替换与key相关联的值
             dictionary[keyIndex].setValue(value);
         else  {
             // 数组已满
             if (isArrayFull())
                 // 将其长度加倍
                 doubleArray();
             // 为由当前的查找确定的索引处的新元素在数组中腾出空间,江汉油田key与value的新元素插入数组中空出的位置
             dictionary[currentSize] =  new  Entry<K, V>(key, value);
             // 词典长度加1
             currentSize++;
         }
         return  result;
     }
     // 返回含有查找键的元素的索引,或者如果元素不存在,返回currentSize
     private  int  locateIndex(K key) {
         int  index =  0 ;
         while ((index < currentSize) && !key.equals(dictionary[index].getKey()))
             index++;
         return  index;
     }
     public  V remove(K key) {
         // 给定查找键,从词典中删除一个元素,并返回该元素的值。如果不存在这样一个元素,则返回null
         V result =  null ;
         // 在数组中查找含有给定查找键的元素
         int  keyIndex = locateIndex(key);
         // 在词典中找到了含有给定查找键的元素
         if (keyIndex < currentSize) {
             // result = 当前与key相关联的值
             result = dictionary[keyIndex].getValue();
             // 用数组的最后一个元素替换该元素
             dictionary[keyIndex] = dictionary[currentSize - 1 ];
             // 词典长度减1
             currentSize --;
         }
         return  result;
     }
}

基于数组的有序词典

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public  class  SortedArrayDictionary<K  extends  Comparable<?  super  K>, V>
         implements  DictionaryInterface<K, V>, Serializable {
     private  Entry<K, V>[] dictionary;  // 无需元素的数组
     private  int  currentSize;  // 元素的数量
     private  final  static  int  DEFAULT_CAPACITY =  25 ;
     public  SortedArrayDictionary() {
         this (DEFAULT_CAPACITY);
     }
     public  SortedArrayDictionary( int  initialCapacity) {
         // 编译器发现,含有Entry类型的元素的数组赋给了含有Entry<K,V>类型的元素的数组。因此,它警告有一个未检验的转换。
         // 试图把新数值转换为Entry<K,V>也将导致一个类似的警告。
         // 这两种情况都不用编译器的警告。
         dictionary =  new  Entry[initialCapacity];
         currentSize =  0 ;
     }
     public  V add(K key, V value) {
         // 讲一个新的键-值元素插入词典并返回null。如果key已在词典中,则返回相应的值,并且用value替换它
         V result =  null ;
         // 查找数组,直到发现含有key的元素,或者找到这样的元素应处的位置
         int  keyIndex = locateIndex(key);
         // key已在词典中
         if ((keyIndex < currentSize) && key.equals(dictionary[keyIndex].getKey())) {
             // result = 当前与key相关联的值
             result = dictionary[keyIndex].getValue();
             // 以value替换与key相关联的值
             dictionary[keyIndex].setValue(value);
         else  // 插入新元素
             // 数组已满
             if (isArrayFull())
                 // 将其长度加倍
                 doubleArray();
             // 移动数组元素,在指定索引处为新元素腾出空间
             makeRoom(keyIndex);
             // 为由前面的查找确定的索引处的新元素在数组中腾出位置,将含有key与value的新元素插入到数组中空出的位置
             dictionary[currentSize] =  new  Entry<K, V>(key, value);
             // 词典长度加1
             currentSize++;
         }
         return  result;
     }
     // 返回含有查找键的元素的索引,或者如果元素不存在,返回currentSize
     private  int  locateIndex(K key) {
         // 进行查找,知道找到一个含有key的元素,或传递它应在的位置
         int  index =  0 ;
         while ((index < currentSize) && key.compareTo(dictionary[index].getKey())>  0 )
             index++;
         return  index;
     }
}

4.基于链表实现词典

使用链表的另一种选择时不使用Entry类。简单的方式是修改节点的定义,使之包含元素的两个部分。

150414463.png

基于链表的无序词典

由于无序词典中的元素没有特定的顺序,所以可用最有效的方法来插入新元素。如果元素是用链表来存放的,则最快的插入方法就是在链表的始端进行插入,插入的效率是O(1)。

基于链表的有序词典

152240815.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public  class  SortedLinkedDictionary<K  extends  Comparable<?  super  K>, V>
         implements  DictionaryInterface<K, V>, Serializable {
     private  Node firstNode;  // 指向链表的第一个结点的引用
     private  int  currentSize;  // 元素的数量
     public  SortedLinkedDictionary() {
         firstNode =  null ;
         currentSize =  0 ;
     }
     private  class  Node<K  extends  Comparable<?  super  K>, V>  implements  Serializable {
         private  K key;
         private  V value;
         private  Node next;
     }
     public  V add(K key, V value) {
         // 将一个新的键-值元素插入词典并返回null。如果key已在词典中,则返回相应的值,并且用value替换它
         V result =  null ;
         // 查找链表,直到找到一个含有key的结点,或者传递它应在的位置
         Node currentNode = firstNode;
         Node nodeBefore =  null ;
         while ((currentNode !=  null ) && key.compareTo(currentNode.getKey()) >  0 ) {
             nodeBefore = currentNode;
             currentNode = currentNode.getNext();
         }
         // 包含key的结点在链表中
         if ((currentNode !=  null ) && key.equals(currentNode.getKey())) {
             // result = 当前与key相关联的值
             result = currentNode.getValue();
             // 用value替换与key相关联的值
             currentNode.setValue(value);
         else  // 链表为空,或者新元素应位于链表始端
             // 为包含key和value的新结点分配存储空间,为该新结点插入到链表始端
             Node newNode =  new  Node(key, value);
             // 词典长度加1
             currentSize++;
             if (nodeBefore ==  null ) {
                 // 在开头插入
                 newNode.setNext(firstNode);
                 firstNode = newNode;
             else  {
                 newNode.setNext(currentNode);
                 nodeBefore.setNext(newNode);
             }
         }
         return  result;
     }
}









本文转自 LinkedKeeper 51CTO博客,原文链接:http://blog.51cto.com/sauron/1227432,如需转载请自行联系原作者
目录
相关文章
|
15天前
|
JSON 监控 算法
员工上网行为监控:利用Scala编写数据处理和分析算法
企业在数字化时代利用Scala进行员工上网行为监控,以确保合规和网络安全。通过Scala的数据处理和分析能力,读取CSV日志数据转换为DataFrame,分析员工行为,如统计最常访问网站。此外,还展示了将监控数据以JSON格式提交至公司网站的函数,实现实时信息更新与安全防护。
58 5
|
3天前
|
机器学习/深度学习 自然语言处理 算法
Python遗传算法GA对长短期记忆LSTM深度学习模型超参数调优分析司机数据|附数据代码
Python遗传算法GA对长短期记忆LSTM深度学习模型超参数调优分析司机数据|附数据代码
|
3天前
|
搜索推荐 C语言
【C语言/数据结构】排序(归并排序|计数排序|排序算法复杂度)
【C语言/数据结构】排序(归并排序|计数排序|排序算法复杂度)
8 0
|
4天前
|
存储 算法
Leetcode 30天高效刷数据结构和算法 Day1 两数之和 —— 无序数组
给定一个无序整数数组和目标值,找出数组中和为目标值的两个数的下标。要求不重复且可按任意顺序返回。示例:输入nums = [2,7,11,15], target = 9,输出[0,1]。暴力解法时间复杂度O(n²),优化解法利用哈希表实现,时间复杂度O(n)。
16 0
|
9天前
|
机器学习/深度学习 算法 数据可视化
Matlab决策树、模糊C-均值聚类算法分析高校教师职称学历评分可视化
Matlab决策树、模糊C-均值聚类算法分析高校教师职称学历评分可视化
|
9天前
|
存储 索引
操作数栈的字节码指令执行分析
操作数栈的字节码指令执行分析
|
10天前
|
存储 算法 Java
22个常用数据结构实现与原理分析
前两天V哥跟一个老学员吃饭,聊起面试大厂的事,说为啥大厂面试第一看基本条件,第二就是考数据结构算法,其他高阶的内容会比较少,最近V哥也在跟大厂对接这一块业务,了解得多一些,这是因为考察基本功能力被放到了重要位置,大厂认为硬性条件,比如学历过关,基本功够扎实,那对于实际工作用的上层技能,内部培养就好,也就是相比你掌握了多少多少牛逼的高阶技术,他们更在乎你的基本功,所以,进大厂,基本功必须要搞稳,否则白扯,今天 V 哥把总结好的22个常用的数据结构实现原理,和示例分析分享给大家,希望对你有帮助,觉得内容有收获,请帮忙转发给更多需求的朋友,共同进步。
|
10天前
|
算法 搜索推荐 数据挖掘
MATLAB模糊C均值聚类FCM改进的推荐系统协同过滤算法分析MovieLens电影数据集
MATLAB模糊C均值聚类FCM改进的推荐系统协同过滤算法分析MovieLens电影数据集
|
10天前
|
算法 数据可视化 数据挖掘
数据分享|R语言改进的K-MEANS(K-均值)聚类算法分析股票盈利能力和可视化
数据分享|R语言改进的K-MEANS(K-均值)聚类算法分析股票盈利能力和可视化
|
10天前
|
存储 机器学习/深度学习 算法