什么是键值对?
C#中用键值对存储数据的都有哪些?
C#中,键值对的复杂度是什么意思?
很大一部分在学习的时候都没有进行总结吧。好吧,本篇做一个小总结。
键值对(key-value)
是一种常见的数据结构,它由一个键(key)和一个值(value)组成。在这种数据结构中,每个键都唯一对应一个值,可以通过键来快速查找和访问其对应的值。键和值之间存在着一 一对应的关系。
比如,我们有一个存储学生信息的系统,每个学生都有一个唯一的学号(键),以及对应的姓名、年龄、性别等信息(值)。在这个系统中,我们可以通过学号来快速查找和获取学生的信息。
在计算机科学和编程领域,键值对通常被用于实现字典(dictionary)、哈希表(hash table)、集合(set)等数据结构。它们在各种编程语言中都有相应的实现,例如在C#中就有Dictionary
键值对常见方式
1、Dictionary
这是一个具有类型参数的泛型类,用于存储键值对。键和值都可以是任何类型。Dictionary类使用哈希表来存储数据,因此查找速度非常快。它是非常常用的存储键值对数据的方式。
完整代码示例:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AllKeyValue
{
internal class Program
{
static void Main(string[] args)
{
Dictionary dict = new Dictionary();
dict.Add("One", 1);
dict.Add("Two", 2);
Console.WriteLine(dict["One"]);//输出值
Console.WriteLine(dict["Two"]);//输出值
}
}
}
复杂度:
* 插入:O(1) 平均情况,O(n) 最坏情况(n 是字典中的元素数)。
* 查找:O(1) 平均情况,O(n) 最坏情况。
* 删除:O(1) 平均情况,O(n) 最坏情况。
2、Hashtable
这是C#中的非泛型类,用于存储键值对。键和值都是object类型,因此需要在使用时进行类型转换。Hashtable也使用哈希表来存储数据,但因为它是非泛型的,所以需要在使用时进行类型转换,这可能会降低性能。
完整示例代码:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AllKeyValue2
{
internal class Program
{
static void Main(string[] args)
{
Hashtable ht = new Hashtable();
ht.Add("One", 1);
ht.Add("Two", 2);
Console.WriteLine(ht["One"]);
Console.WriteLine(ht["Two"]);
}
}
}
复杂度:与Dictionary类似,但可能在运行时出现额外的类型转换开销。
3、 SortedDictionary
这是一个泛型类,用于存储键值对,并且键是有序的。它使用平衡二叉搜索树来存储数据,因此查找速度相对较慢,但键是有序的。
完整示例代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AllKeyValue3
{
internal class Program
{
static void Main(string[] args)
{
SortedDictionary sd = new SortedDictionary();
sd.Add("One", 1);
sd.Add("Two", 2);
Console.WriteLine(sd["One"]);
Console.WriteLine(sd["Two"]);
}
}
}
复杂度:
* 插入:O(log n)。
* 查找:O(log n)。
* 删除:O(log n)。
4、SortedList
这是一个泛型类,用于存储键值对,并且键是有序的。它使用链表来存储数据,因此查找速度相对较慢,但键是有序的。
完整示例代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AllKeyValue4
{
internal class Program
{
static void Main(string[] args)
{
SortedList sl = new SortedList();
sl.Add("One", 1);
sl.Add("Two", 2);
Console.WriteLine(sl["One"]);
Console.WriteLine(sl["Two"]);
}
}
}
复杂度:与SortedDictionary类似,但在内存使用上可能更高效。
5.、NameValueCollection
这是一个非泛型类,用于存储键值对。它通常用于存储表单数据或查询字符串。
完整示例代码:
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AllKeyValue5
{
internal class Program
{
static void Main(string[] args)
{
NameValueCollection nvc = new NameValueCollection();
nvc.Add("One", "1");
nvc.Add("Two", "2");
Console.WriteLine(nvc["One"]);
Console.WriteLine(nvc["Two"]);
}
}
}
复杂度:与Dictionary类似,但键和值都是字符串类型。
6、ConcurrentDictionary
这是一个泛型类,用于在多线程环境下存储键值对。它使用哈希表来存储数据,并且提供了一些线程安全的方法。
完整示例代码:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AllKeyValue6
{
internal class Program
{
static void Main(string[] args)
{
ConcurrentDictionary cd = new ConcurrentDictionary();
cd.TryAdd("One", 1);
cd.TryAdd("Two", 2);
Console.WriteLine(cd["One"]);
Console.WriteLine(cd["Two"]);
}
}
}
复杂度:与Dictionary类似,但提供了线程安全的操作。在多线程环境下使用可以提高性能和数据一致性。但需要注意,线程安全操作可能会引入额外的开销。
下面的概念有些是新的概念,前面也没有引入(比如红黑树、二叉树等),有印象就行,不用急着去记住。
键值对的复杂度
键值对的复杂度是指在数据结构中插入、查找和删除键值对操作的时间复杂程度。这些操作是许多数据处理系统中常见的基本操作,例如在哈希表、字典、集合等数据结构中。
对于键值对数据结构,插入、查找和删除操作的复杂度通常由其底层实现的数据结构决定。以下是常见的一些时间复杂度:
- 哈希表(HashTable):
插入(Insertion):O(1),在平均情况下,哈希表的插入操作可以在常数时间内完成。
查找(Search):O(1),在平均情况下,哈希表的查找操作可以在常数时间内完成。
删除(Deletion):O(1),在平均情况下,哈希表的删除操作可以在常数时间内完成。
- 平衡二叉搜索树(Balanced Binary Search Tree,如AVL树或红黑树):
插入(Insertion):O(log n),在平衡二叉搜索树中,插入操作的平均时间复杂度为对数级别。
查找(Search):O(log n),在平衡二叉搜索树中,查找操作的平均时间复杂度为对数级别。
删除(Deletion):O(log n),在平衡二叉搜索树中,删除操作的平均时间复杂度为对数级别。
- 数组(Array):
插入(Insertion):O(n),在数组的开头插入元素需要移动所有后面的元素。
查找(Search):O(n),在数组中查找元素需要遍历整个数组。
删除(Deletion):O(n),在数组的开头删除元素需要移动所有后面的元素。
这里的复杂度通常是指在最坏情况下的时间复杂度,但实际运行时间可能会因具体情况而有所不同。在设计数据结构和算法时,根据实际应用场景选择具有合适复杂度的数据结构和算法是非常重要的。