今日学习了:泛型约束、泛型数据集合List、LinkedList、Dictionary、Stack、Queue、顺序存储和链式存储
1.泛型约束
目的:让泛型类型有一定的限制
关键字:where
六种泛型约束
1.值类型 where 泛型字母:struct
2.引用类型 where 泛型字母:class
3.存在公共无参构造方法的非抽象类型 where 泛型字母:new()
4.某个类本身或其派生类 where 泛型字母:类名
5.某个接口的派生类型(可以是接口本身或者派生接口也可以是实现的类,是接口本身或派生接口因为接口无法实例化使用时涉及里氏替换原则) where 泛型字母:接口名
例如:
interface IFly
{
}
interface IMove :IFly { }
class test4 :IMove
{
}
class Move<T> where T : IFly
{
public T Value { get; set; }
}
// Move<IMove> move = new Move<IMove>();
// move.Value = new test4();
6.另一个泛型类型本身或者派生类型 where 泛型字母:另一个泛型字母
约束的组合使用
class Test7<T> where T : IFly,new()
{
}
多个泛型约束
class Test8<T,K> where T:IFly,new() where K : T, new()
{
}
2.List
List的本质是可变类型的泛型数组,实现了很多方法
List的声明
List<int> list = new List<int>();
增删查改
增:
list.Add(10); 单个增到后面
list.Insert(0,2); Insert()指定下标位置插入元素
list.AddRange(list2); AddRange()把另一个list里的内容加到后面
删:
list.Remove(10); 从头找删掉指定元素,如果有多个1,会删除第一个1
list.RemoveAt(0); 移除指定下标位置的元素
list.Clear(); 清空
查
Console.WriteLine(list[0]);//[下标]查找指定下标元素
if(list.Contains(1)) //查找list存不存在指定元素
{
Console.WriteLine("存在元素1");
}
Console.WriteLine(list.IndexOf(1));从前往后找指定元素并返回其下标,如果不存在返回-1,如果有多个指定元素,返回从前往后第一个
Console.WriteLine(list.LastIndexOf(1));//从后往前找指定元素并返回其下标,如果不存在返回-1,如果有多个指定元素,返回从后往前第一个
Console.WriteLine(list.Capacity);//.Capacity存储容量,是List种数组的实际容量,.Count的为当前所存储的元素个数
改:
list[0] = 10;//直接修改
简述List和ArrayList的区别
List内部封装的是一个泛型数组,ArrayList内部封装的是一个Object数组
3.Dictionary
Dictionary的本质
可以理解为拥有泛型的Hashtable
它也是基于键的代码组织起来的键值对
键值对由Hashtable的object变成了可以自己指定的泛型
声明
Dictionary<int,string> keyValuePairs = new Dictionary<int,string>();
增删查改
增
keyValuePairs.Add(1, "123");
//同样不能添加以及存在的相同的key,否则运行会报错
//keyValuePairs.Add(1, "234");
删
1.只能通过键去删除
keyValuePairs.Remove(1);
keyValuePairs.Remove(4);//同样没有对应的key不做反应
2.清空
keyValuePairs.Clear();
查
1.通过键来查找
找不到,不同于Hashtable返回空,这里会报错
Console.WriteLine(keyValuePairs[1]);
2.查看是否存在
//根据键检测
if(keyValuePairs.ContainsKey(0))
{
Console.WriteLine("存在key为0的");
}
//根据值检测
if(keyValuePairs.ContainsValue("123"))
{
Console.WriteLine("存在值为\"123\"的键值对");
}
改
keyValuePairs[1] = "555";
遍历:
foreach遍历keys:
foreach(int i in keyValuePairs.Keys) {
Console.Write(i+":");
Console.WriteLine(keyValuePairs[i]);
}
foreach遍历values:
foreach(string st in keyValuePairs.Values)
{
Console.WriteLine(st);
}
foreach遍历KeyValuePair<>:
foreach (KeyValuePair<int,string> obj in keyValuePairs) {
Console.WriteLine(obj);
}
4.顺序存储与链式存储
数据结构
数据结构是指相互之间存在一种或者多种特定关系的数据元素的集合
"面试常考":常用的数据结构 数组、栈、队列、链表、树、图、堆、散列表
线性表 是由n个具有相同特性的数据元素的有限序列
比如数组、ArrayList、Stack、Queue、链表等等
顺序存储和链式存储
顺序存储:用一组地址连续的存储单元一次存储线性表的各个数据元素
链式存储:
单向链表,双向链表,循环链表 --链式存储
用一组任意的存储单元存储线性表的各个数据元素
顺序存储和链式存储的优缺点
从增删改查的角度思考
增:链式存储 计算上 优于顺序存储 (中间插入时不用像数组一样去依依移动元素位置)
删:链式存储 计算上 优于顺序存储 (中间删除时不用像数组一样去依依移动元素位置)
查:顺序存储 使用上 优于链式存储 (数组可以直接通过下标得到元素,链式需要遍历
改:顺序存储 使用上 由于链式存储 (数组可以直接通过下标得到元素,链式需要遍历)
描述顺序存储和链式存储的区别
顺序存储的存储内存地址是连续的(连续地址存储)
链式存储的存储内存地址是随机的(任意地址存储)
实现一个双向链表,并提供以下方法属性,数据的个数,头节点,尾节点,增加数据到链表最后,删除指定位置节点:
class LinkedNode<T>
{
public T Value;
public LinkedNode<T> nextNode;
public LinkedNode<T> preNode;
public LinkedNode(T Value)
{
this.Value = Value;
}
}
class LinkedList<T>
{
public LinkedNode<T> head;
public LinkedNode<T> last;
public int Count { get; private set; }
public LinkedList()
{
Count = 0;
}
public void Add(T Value)
{
LinkedNode<T> Node = new LinkedNode<T>(Value);
if (head == null)
{
head = Node;
last = Node;
}else
{
last.nextNode = Node;
Node.preNode=last;
last=Node;
}
Count++;
}
public void Remove(T Value)
{
LinkedNode<T> Node = head;
if (head.Value.Equals(Value))
{
head = head.nextNode;
head.preNode = null;
if (head == null) last = null;
Count--;
return;
}
while(Node != null)
{
if (Node.Value.Equals(Value))
{
if (Node == last)
{
last = Node.preNode;
Node.preNode.nextNode = null;
Node.preNode = null;
}
else
{
Node.preNode.nextNode = Node.nextNode;
Node.nextNode.preNode = Node.preNode;
}
Count--;
return;
}
Node = Node.nextNode;
}
}
public void RemoveAt(int index)
{
if (index < 0 || index >= Count) return;
Count--;
LinkedNode<T> Node = head;
for(int i=0;i<index;i++)
{
Node=Node.nextNode;
}
if (Node == head)
{
head=head.nextNode;
head.preNode = null;
if (head == null) last = null;
}else if(Node == last)
{
last = Node.preNode;
Node.preNode.nextNode = null;
Node.preNode = null;
}
else
{
Node.preNode.nextNode = Node.nextNode;
Node.nextNode.preNode = Node.preNode;
}
}
}
5.LinkedList
Linkedlist的本质
是一个可变类型的泛型双向链表
申明
LinkedList<int> list = new LinkedList<int>();
节点类型 LinkedListNode<T>
增删查改
增
1.在链表尾部添加元素
list.AddLast(1);
2.在链表头部添加元素
list.AddFirst(2);
3.在某个节点之后添加元素
LinkedListNode<int> Node = list.Find(5);
list.AddAfter(Node, 6);
4..在某个结点之前添加元素
list.AddBefore(Node, 7);
删
1.移除头节点
list.RemoveFirst();
2.移除尾节点
list.RemoveLast();
3.移除指定节点
| Remove(LinkedListNode<T>) | 从 LinkedList<T> 中移除指定的节点。 |
| Remove(T) | 从 LinkedList<T> 中移除指定值的第一个匹配项。 |
4.清空
list.Clear();
查
1.查到头节点
LinkedListNode<int> first = list.First;
2.查到尾节点
LinkedListNode<int> last = list.Last;
3.查找指定值的节点
LinkedListNode<int> node = list.Find(5);//找不到会返回空
4.判断是否存在
list.AddLast(1);
if (list.Contains(1))
{
Console.WriteLine("存在1");
}
改
Console.WriteLine(list.First.Value);
list.First.Value = 10;
Console.WriteLine(list.First.Value);
遍历
1.foreach遍历 直接得到node里的value
foreach (int item in list)
{
Console.WriteLine(item);
}
2.通过node
// 从头到尾
LinkedListNode<int> temp = list.First;
while (temp != null)
{
Console.WriteLine(temp.Value);
temp = temp.Next;
}
temp = list.Last;
Console.WriteLine("------------------------");
while (temp != null)
{
Console.WriteLine(temp.Value);
temp = temp.Previous;
}
5.泛型Stack与Queue
回顾数据容器
变量 :
无符号 byte ushort uint ulong
有符号 sbyte short int long
浮点数 float double decimal
特殊
char bool string
复杂数据类型
enum
struct
class
数组(一维,二维,交错) [] [,] [][]
数据集合
ArrayList object数据列表
Stack 栈
Queue 队列
Hashtable 哈希表
泛型数据集合 用的更多
List 泛型列表
Dictionary 泛型哈希表
Linkedlist 泛型双向链表
Stack<T> 泛型栈
Queue<T> 泛型队列
泛型栈与队列 与 栈和队列的方法一致
声明
Stack<int> stack = new Stack<int>();
Queue<int> q = new Queue<int>();
总结数组 List Dictionary Stack Queue LinkedList这些容器,如何合理使用?
普通线性表
数组,List,LinkedList
数组:固定的不变的一组数据
List:经常改变,经常通过下标查找
LinkedList:不确定长度,经常临时插入改变,查找不多
先进后出:
Stack
对于一些可以利用先进后出存储特点的逻辑
比如:UI面板显隐规则
先进先出
Queue
对于一些可以利用先进先出存储特点的逻辑
比如:消息队列
键值对:
Dictionary
需要频繁查找,有对应关系的数据
比如一些数据存储 id对应数据内容
3907

被折叠的 条评论
为什么被折叠?



