c#中常用数据结构有数组、链表、集合、哈希散列。
数组包括:Array、ArrayList、List<T>
链表包括:LinkedList、Queue、Stack
集合包括:HashSet、SortedSet
哈希散列包括:Hashtable、Dictionary
数组:Array
{
Console.WriteLine("**************** Array 数组 *********************");
int[] intArr = new int[] { 1, 2, 3 };
intArr[0] = 100;
Console.WriteLine(intArr[0]);
foreach (var item in intArr)
{
Console.WriteLine(item);
}
}
执行结果:
数组:ArrayList
{
Console.WriteLine("**************** ArrayList 数组 *********************");
var obj = new { name = "李四", age = "20" };
ArrayList arrayList = new ArrayList();
arrayList.Add("张三");
arrayList.Add(18);
arrayList.Add(obj);
Console.WriteLine(arrayList[1]);
foreach (var item in arrayList)
{
Console.WriteLine(item);
}
}
执行结果:
ArrayList数组,元素没有类型限制,何元素都可以被当做object处理,如果是值类型,会有装箱操作。
数组:List<T>
{
Console.WriteLine("**************** List<T> 数组 *********************");
List<int> intList = new List<int>();
intList.Add(1);
intList.Add(100);
Console.WriteLine(intList[0]);
foreach (var item in intList)
{
Console.WriteLine(item);
}
}
执行结果:
List<T>是数组的泛型版本,保证类型安全,避免装箱拆箱操作,实际开发中运用最多。
数组的特点:
1.数据在内存中连续存储,节约空间。
2.可以使用下标索引访问。
3.读取快,增删慢。
链表:LinkedList
{
Console.WriteLine("**************** 双向链表 LinkedList *********************");
LinkedList<int> linkedList = new LinkedList<int>();
linkedList.AddFirst(111);
linkedList.AddLast(222);
bool isContain = linkedList.Contains(111);
LinkedListNode<int> node = linkedList.Find(111);//查找元素123的位置,从头查找
linkedList.AddBefore(node, 333);//在node结点前加入元素333
linkedList.AddAfter(node, 444);//在node结点后插入元素444
foreach (var item in linkedList)
{
Console.WriteLine(item);
}
linkedList.Remove(111);//移除元素111
linkedList.RemoveFirst();//移除开头元素
linkedList.RemoveLast();//移除末尾元素
linkedList.Clear();//清除所有元素
}
执行结果:
LinkedList为双向链表,链表在内存中的空间不是连续的,每块空间称作一个节点,每个节点都存有与它之前和之后相连接的节点的地址,因此向链表中添加和删除元素时只需要更改相关节点存储的地址的指向,效率高。
查找元素时不能通过下标访问,只能从头开始通过地址按顺序查找,效率低。
链表:Queue
{
Console.WriteLine("**************** 队列 Queue *********************");
Queue<string> queue = new Queue<string>();
queue.Enqueue("a");//添加元素
queue.Enqueue("b");
queue.Enqueue("c");
foreach (var item in queue)
{
Console.WriteLine(item);
}
Console.WriteLine($"queue.Dequeue:{ queue.Dequeue() }");//移除元素 并返回当前元素内容
Console.WriteLine($"queue.Peek:{ queue.Peek() }");//查询开头元素
foreach (var item in queue)
{
Console.WriteLine(item);
}
}
执行结果:
Queue名称为队列,本质上也属于链表。先进先出的原则,最先插入的元素最先被访问,最后插入的元素最后被访问。
可以看做是去食堂打饭排队,先到的先打饭。
链表:Stack
{
Console.WriteLine("**************** Stack 堆栈 *********************");
Stack<int> stack = new Stack<int>();
stack.Push(1);
stack.Push(2);
stack.Push(3);
foreach (var item in stack)
{
Console.WriteLine(item);
}
Console.WriteLine($"stack.Pop:{stack.Pop()}");//获取栈顶元素并移除
Console.WriteLine($"stack.Peek:{stack.Peek()}");//获取栈顶元素
Stack<int> stack1 = new Stack<int>(stack.ToArray());
foreach (var item in stack1)
{
Console.WriteLine(item);
}
}
执行结果:
Stack名称为堆栈,本质上也属于链表。先进后出原则,最先插入的元素最后被访问,最后被插入的元素最先被访问。
可以看做是往水桶中装水,先装进去的水最后被舀出来,最后装进去的水先被舀出来。
集合:HashSet
{
Console.WriteLine("**************** 集合 HashSet *********************");
HashSet<string> hashSet = new HashSet<string>();
hashSet.Add("a");
hashSet.Add("b");
hashSet.Add("d");
hashSet.Add("c");
hashSet.Add("a");
foreach (var item in hashSet)
{
Console.WriteLine(item);
}
Console.WriteLine($"hashSet.Count:{hashSet.Count}");
Console.WriteLine($"hashSet.Contains:{hashSet.Contains("a")}");
{
HashSet<string> hashSet1 = new HashSet<string>();
hashSet1.Add("d");
hashSet1.Add("e");
hashSet1.Add("f");
hashSet1.SymmetricExceptWith(hashSet);//补集 hashSet1被修改为 e,f,a,b,c
hashSet1.UnionWith(hashSet);//并集 hashSet1被修改为 d,e,f,a,b,c
hashSet1.ExceptWith(hashSet);//差集(hashSet1-hashSet) hashSet1被修改为 e,f
hashSet1.IntersectWith(hashSet);//交集 hashSet1被修改为 d
}
hashSet.ToList();
hashSet.Clear();
}
执行结果:
HashSet是纯粹的集合,可以理解为一个容器,把东西放进去,具有唯一性。放进去的元素会自动被去重。
可以拿 HashSet来统计用户访问某网站的IP地址,这样就会得到没有重复的记录。
集合:SortedSet
{
Console.WriteLine("**************** 集合 SortedSet *********************");
SortedSet<string> sortedSet = new SortedSet<string>();
sortedSet.Add("a");
sortedSet.Add("b");
sortedSet.Add("d");
sortedSet.Add("c");
sortedSet.Add("a");
foreach (var item in sortedSet)
{
Console.WriteLine(item);
}
Console.WriteLine($"hashSet.Count:{sortedSet.Count}");
Console.WriteLine($"hashSet.Contains:{sortedSet.Contains("a")}");
{
SortedSet<string> sortedSet1 = new SortedSet<string>();
sortedSet1.Add("d");
sortedSet1.Add("e");
sortedSet1.Add("f");
sortedSet1.SymmetricExceptWith(sortedSet);//补集 hashSet1被修改为 e,f,a,b,c
sortedSet1.UnionWith(sortedSet);//并集 hashSet1被修改为 d,e,f,a,b,c
sortedSet1.ExceptWith(sortedSet);//差集(hashSet1-hashSet) hashSet1被修改为 e,f
sortedSet1.IntersectWith(sortedSet);//交集 hashSet1被修改为 d
}
sortedSet.ToList();
sortedSet.Clear();
}
执行结果:
SortedSet是自动排序的集合,也可以自动去重。
跟HashSet相比,多了一个排序功能。
如果需要元素去重且需要排序,用这个是比较合适的。
哈希散列:Hashtable
{
Console.WriteLine("**************** 哈希散列 Hashtable *********************");
Hashtable hashtable = new Hashtable();
hashtable.Add("a", 1);
hashtable[111] = 123;
foreach (DictionaryEntry entry in hashtable)
{
Console.WriteLine($"entry.Key:{entry.Key}");
Console.WriteLine($"entry.Value:{entry.Value}");
}
//线程安全
Hashtable.Synchronized(hashtable);//只有一个线程写 多个线程度
}
执行结果:
Hashtable中的key和value都是object类型的。
Hashtable中key的值如果重复,后者的值会覆盖前者的值。
Hashtable详细讲解参考:https://www.cnblogs.com/chenmfly/p/4883106.html
哈希散列:Dictionary
{
Console.WriteLine("**************** 字典 *********************");
Dictionary<int, string> dic = new Dictionary<int, string>();
dic.Add(1, "a");
dic.Add(2, "b");
foreach (var item in dic)
{
Console.WriteLine($"entry.Key:{item.Key}");
Console.WriteLine($"entry.Value:{item.Value}");
}
foreach (KeyValuePair<int, string> keyValuePair in dic)
{
Console.WriteLine($"entry.Key:{keyValuePair.Key}");
Console.WriteLine($"entry.Value:{keyValuePair.Value}");
}
}
执行结果:
Dictionary名称为字典,可以理解为Hashtable的泛型版本。在实际开发中广泛应用。
字典中key的值必须唯一。
哈希散列的特点:
1.都是以key-value形式存储数据。
2.可以通过key快速查找对应的value,速度快,但是消耗内存。