C#是一种安全的、稳定的、简单的、优雅的,由C和C++衍生出来的面向对象的编程语言。它在继承C和C++强大功能的同时去掉了一些它们的复杂特性(例如没有宏以及不允许多重继承)。C#综合了VB简单的可视化操作和C++的高运行效率,以其强大的操作能力、优雅的语法风格、创新的语言特性和便捷的面向组件编程的支持成为.NET开发的首选语言。
接下来,我会介绍C#的数据结构。
数组
同一类型和不同类型的多个对象
- 同一类型多个对象
- 可以使用集合和数组管理。
- C#用特殊的记号声明、初始化和使用数组。
- Array类在后台发挥作用,它为数组中元素的排序和过滤提供了几个方法。
- 使用枚举器,可以迭代数组中的所有元素。
- 不同类型多个对象
- 可以使用Tuple(元组)类型管理。
数组类型
- 一维数组
- 多维数组
- 锯齿数组
多维数组,行和列是固定的:
int[][] arrMore=new int[3][6];
锯齿数组只要在第一个方括号设置行数,每行的个数是可变的。
int[][] jagged=new int[3][];
jagged[0]=new int[2]{1,2};
jagged[1]=new int[6]{1,2,3,4,5,6};
jagged[2]=new int[3]{1,2,3};
Array
Array 类是 C# 中所有数组的基类,它是在 System 命名空间中定义(System.Array)。Array 类提供了各种用于数组的属性和方法。
用方括号声明数组是C#中使用Array类的表示法。在后台使用C#语法,会创建一个派生自抽象基类Array的新类。这样,就可以使用Array类为每个C#数组定义的方法和属性了。
创建数组
Array类是一个抽象类,所以不能使用构造函数来创建数组。但除了可以使用C#语法创建数组实例之外,还可以使用静态方法CreateInstance()创建数组。如果事先不知道元素的类型,该静态方法就非常有用,因为类型可以作为Type对象传递给CreateInstance()方法。
例如:
Array arr=Array.CeateInstance(typeof(int),5);
for(int i=0;i<5;i++)
{
arr.SetVaule(i,i);
}
for(int i=0;i<5;i++)
{
int vaule=arr.getVaule(i);
}
栈
Stack
堆栈(Stack)代表了一个后进先出的对象集合。当您需要对各项进行后进先出的访问时,则使用堆栈。当您在列表中添加一项,称为推入元素,当您从列表中移除一项时,称为弹出元素。
- 栈以及泛型栈
public class Stack<T> : IEnumerable<T>, ICollection, IEnumerable
public class Stack : ICollection, IEnumerable, ICloneable
队列
Queue
队列(Queue)代表了一个先进先出的对象集合。当您需要对各项进行先进先出的访问时,则使用队列。当您在列表中添加一项,称为入队,当您从列表中移除一项时,称为出队。
- 队列以及泛型队列
public class Queue : ICollection, IEnumerable, ICloneable
public class Queue<T> : IEnumerable<T>, IEnumerable, IReadOnlyCollection<T>, ICollection
链表
单链表
- 啥是单链表?
单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。这组存储单元既可以是连续的,也可以是不连续的。
链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。 - 链表的结点结构
┌───┬───┐
│data│next │
└───┴───┘
data域--存放结点值的数据域[元素]
next域--存放结点的直接后继的地址(位置)的指针域(链域)[指针]
实现方式
public class Node<T>
{
public T Data { set; get; } //数据域,当前结点数据
public Node<T> Next { set; get; } //位置域,下一个结点地址
public Node(T item)
{
this.Data = item;
this.Next = null;
}
public Node()
{
this.Data = default(T);
this.Next = null;
}
}
请转到《数据结构:单链表》查看更详细内容!
双向链表
LinkedList是一个双向链表,其元素会指向它前面和后面的元素。这样,通过移动到下一个元素可以正向遍历链表,通过移动到前一个元素可以反向遍历链表。
链表在存储元素时,不仅要存储元素的值,还必须存储每个元素的下一个元素和上一个元素的信息。这就是LinkedList包含LinkedListNode类型的元素的原因。使用LinkedListNode,可以获得列表中的下一个和上一个元素。LinkedListNode定义了属性List,Next,Previous和Value。List属性返回与节点相关的LinkedList对象。Next和Previous属性用于遍历链表,访问当前节点之后和之前的节点。Value属性返回与节点相关的元素,其类型是T。
链表的优点是,如果将元素插入到列表的中间位置,使用链表就会很快。在插入一个元素时,只需要修改上一个元素的Next引用和下一个元素的Previous引用,使它们引用所插入的元素。在List中,插入一个元素,需要移动该元素后面的所以元素。
链表的缺点是,链表元素只能一个接一个的访问,这需要较长时间来查找位于链表中间或尾部的元素。
LinkedList类定义的成员可以访问链表中的第一个和最后一个元素(First和Last);
在指定位置插入元素:AddAfter(),AddFirst()和AddLast();
删除指定位置的元素:Remove(),RemoveFirst(),RemoveLast();
搜索:Find(),FindLast()。
树
C#中没有实现树的具体类,一般可以通过自己实现。
结点树包含:父结点(根结点的父结点为null)、子结点(List集合)、数据对象。
请转到《 数据结构:树》查看更详细的内容!
图
图状结构简称图,是另一种非线性结构,它比树形结构更复杂。树形结构中的结点是一对多的关系,结点间具有明显的层次和分支关系。每一层的结点可以和下一层的多个结点相关,但只能和上一层的一个结点相关。而图中的顶点(把图中的数据元素称为顶点)是多对多的关系,即顶点间的关系是任意的,图中任意两个顶点之间都可能相关。也就是说,图的顶点之间无明显的层次关系,这种关系在现实世界中大量存在。因此,图的应用相当广泛,在自然科学、社会科学和人文科学等许多领域都有着非常广泛的应用。
c#没有实现图的数据结构,但是可以自己实现,参考如下
请转到《数据结构:图》查看更详细内容!
字典树
c#也没有实现字典树,可以自己实现,参考如下
请转到《数据结构:字典树》查看更详细内容!
散列表(哈希表)
哈希表(HashTable)简述
Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似keyvalue的键值对,其中key通常可用来快速查找,同时key是区分大小写;value用于存储对应于key的值。Hashtable中keyvalue键值对均为object类型,所以Hashtable可以支持任何类型的keyvalue键值对.
什么情况下使用哈希表
- 某些数据会被高频率查询
- 数据量大
- 查询字段包含字符串类型
- 数据类型不唯一
使用方法
- 哈希表需要使用的namespace
using System.Collections;
using System.Collections.Generic;
- 哈希表的基本操作:
//添加一个keyvalue键值对:
HashtableObject.Add(key,value);
//移除某个keyvalue键值对:
HashtableObject.Remove(key);
//移除所有元素:
HashtableObject.Clear();
// 判断是否包含特定键key:
HashtableObject.Contains(key);
- 遍历哈希表
遍历哈希表需要用到DictionaryEntry Object,代码如下:
for(DictionaryEntry de in ht) //ht为一个Hashtable实例
{
Console.WriteLine(de.Key); //de.Key对应于keyvalue键值对key
Console.WriteLine(de.Value); //de.Key对应于keyvalue键值对value
}
请转到《数据结构:哈希表》查看更详细内容!