C#学习记录--更新中
- C#进阶
- ArrayList
- 增删查改
- 装箱拆箱
- 练习
- ArrayList和数组的区别
- ArrayList和List的区别
- Stack
- Stack的本质
- 增取查改
- 遍历
- 装箱拆箱
- 栈的存储规则
- 练习
- Queue
- 增取查改
- 装箱拆箱
- 队列的存储规则
- 练习
- Hashtable散列表
- Hashtable的本质
- 增删查改
- 遍历
- 装箱拆箱
- Hashtable的存储规则
- 练习
- 泛型
- 泛型是什么
- 泛型分类
- 泛型方法
- 泛型的作用
- 练习题
- 泛型约束
- 什么是泛型约束
- 各泛型约束讲解
- 值类型约束
- 引用类型约束
- 存在无参公共构造函数
- 类约束
- 接口约束
- 另一个泛型约束
- 约束的组合使用
- 多个泛型有约束
- 练习
- List
- 增删查改
- 遍历
- List和ArrayList的区别
- 练习
- Dictionary
- Dictionary的本质
- 增删查改
- 遍历
- 练习
- 顺序存储和链式存储
- 数据结构
- 线性表
- 顺序存储
- 链式存储
- 自己实现一个最简单的单向链表
- 顺序存储和链式存储的优缺点
- 常用的数据结构有哪些
- 顺序存储和链式存储的区别
- 练习
- LinkedList
- 增删查改
- 遍历
- 练习
- 数据容器
- 变量
- 复杂数据容器
- 数据集合
- 泛型数据集合
- 泛型栈和队列
- 如何使用数据容器
C#进阶
ArrayList
ArrayList是一个C#为我们封装好的类,
它的本质是一个object类型的数组,
ArrayList类帮助我们实现了很多方法,
比如数组的增删查改
//需要引用命名空间using System.Collections;
ArrayList array = new ArrayList();
增删查改
增
array.Add(1);array.Add(new Test());array.Add("123");
//加一个ArrayList
ArrayList array2 = new ArrayList();
array2.AddRange(array2);
删
// 移除指定元素,从头找
array.RemoveAt(1);
//指定位置
array.RemoveAt(2);
array.Clear();
查
//得到指定位置的元素
Console.WriteLine(array[0]);//查看元素是否存在
if( array.Contains("1234") )
{Console.WriteLine("存在123");
}//正向查找元素位置
//找到的返回值 是位置 找不到 返回值 是-1
int index = array.IndexOf(true);
Console.WriteLine(index);Console.WriteLine(array.IndexOf(false));//反向查找元素位置
//返回时从头开始的索引数
index = array.LastIndexOf(true);Console.WriteLine(index);
#endregionif (array.Contains("123"))
{Console.WriteLine("存在123");
}
改
Console.WriteLine(array[0]);array[0] = "999";Console.WriteLine(array[0]);array.Insert(1, "1236547");
遍历
//长度
Console.WriteLine(array.Count);
//容量
//避免产生过多的垃圾
Console.WriteLine(array.Capacity);Console.WriteLine("***********************");
for (int i = 0; i < array.Count; i++)
{Console.WriteLine(array[i]);
}
Console.WriteLine("***********************");
//迭代器遍历
foreach (object item in array)
{Console.WriteLine(item);
}
装箱拆箱
装箱就是把栈上的内存转移到堆上面,拆箱就是把堆上面的内存转移到栈上面
ArrayList本质上是一个可以自动扩容的object数组
当往其中进行值类型存储时就是在装箱,当将值类型对象取出来转换使用时,就存在拆箱
int k = 1;array[0] = k;//装箱k = (int)array[0];//拆箱
练习
创建一个背包管理类,使用ArrayList存储物品,
实现购买物品,卖出物品,显示物品的功能。购买与卖出物品会导致金钱变化
ArrayList和数组的区别
- ArrayList可以不用一开始就是定长的,而数组是定长的
- ArrayList默认是object类型,而数组可以指定存储类型
- ArrayList封装了很多增删查改API,而数组需要自己实现
- ArrayList使用时候存在装箱拆箱,而数组只要使用时候不是object数组就不存在这个问题
- 数组长度为Length,ArrayList长度为Count,容量为Capecity
ArrayList和List的区别
- ArrayList 不带泛型 数据类型丢失,而List 带泛型 数据类型不丢失
- ArrayList 需要装箱拆箱 List不需要
- 在声明List集合时,我们同时需要为其声明List集合内数据的对象类型(带泛型)
ArrayList存在不安全类型(ArrayList会把所有插 ⼊其中的数据都当做Object来处理)装箱拆箱的 操作(费时)IList是接⼝,ArrayList是⼀个实现了 该接⼝的类,可以被实例化
List类是ArrayList类的泛型等效类。它的大部分用法都与ArrayList相似,因为List类也继承了IList接口。最关键的区别在于,在声明List集合时,我们同时需要为其声明List集合内数据的对象类型。
Stack
Stack的本质
它的本质也是object[]数组,只是封装了特殊的存储规则
栈是先进后出
Stack(栈)是一个C#为我们封装好的类Stack是栈存储容器,栈是一种先进后出的数据结构
先存入的数据后获取,后存入的数据先获取
//需要引用命名空间 System.Collections
Stack stack = new Stack();
增取查改
增
//压栈
stack.Push(231);
stack.Push(1);
stack.Push("123");
stack.Push(true);
stack.Push(1.2f);
stack.Push(new Test());
取
//栈中不存在删除的概念
//只有取的概念
//弹栈
object v = stack.Pop();Console.WriteLine(v);v = stack.Pop();
Console.WriteLine(v);
查
//1.栈无法查看指定位置的 元素
// 只能查看栈顶的内容
v = stack.Peek();
Console.WriteLine(v);
v = stack.Peek();
Console.WriteLine(v);//2.查看元素是否存在于栈中
if( stack.Contains("123") )
{Console.WriteLine("存在123");
}
改
//栈无法改变其中的元素 只能压(存)和弹(取)
//实在要改 只有清空
stack.Clear();
Console.WriteLine(stack.Count);
stack.Push("1");
stack.Push(2);
stack.Push("哈哈哈");
遍历
//1.长度
Console.WriteLine(stack.Count);//2.用foreach遍历
// 而且遍历出来的顺序 也是从栈顶到栈底
foreach(object item in stack)
{Console.WriteLine(item);
}//3.还有一种遍历方式
// 将栈转换为object数组
// 遍历出来的顺序 也是从栈顶到栈底
object[] array = stack.ToArray();
for (int i = 0; i < array.Length; i++)
{Console.WriteLine(array[i]);
}Console.WriteLine(stack.Count);
//4.循环弹栈
while( stack.Count > 0 )
{object o = stack.Pop();Console.WriteLine(o);
}
Console.WriteLine(stack.Count);
装箱拆箱
由于用万物之父来存储数据,自然存在装箱拆箱。
当往其中进行值类型存储时就是在装箱
当将值类型对象取出来转换使用时,就存在拆箱。
栈的存储规则
先进后出
练习
写一个方法计算任意一个数的二进制数
使用栈结构方式存储,之后打印出来
Queue
它的本质也是object[]数组,只是封装了特殊的存储规则
先进先出
Queue是一个C#为我们封装好的类Queue是队列存储容器
队列是一种先进先出的数据结构
先存入的数据先获取,后存入的数据后获取
//需要引用命名空间 System.Collections
Queue queue = new Queue();
增取查改
增
queue.Enqueue(1);
queue.Enqueue("123");
queue.Enqueue(1.4f);
queue.Enqueue(new Test());queue.Enqueue("!23");
取
//队列中不存在删除的概念
//只有取的概念 取出先加入的对象
object v = queue.Dequeue();
Console.WriteLine(v);
v = queue.Dequeue();
Console.WriteLine(v);
查
//1.查看队列头部元素但不会移除
v = queue.Peek();
Console.WriteLine(v);
v = queue.Peek();
Console.WriteLine(v);v = quque.Peek();//2.查看元素是否存在于队列中
if( queue.Contains(1.4f) )
{Console.WriteLine("队列中存在1.4f");
}
改
//1.长度
Console.WriteLine(queue.Count);
//2.用foreach遍历
foreach (object item in queue)
{Console.WriteLine(item);
}
//3.还有一种遍历方式
// 将队列转换为object数组
object[] array = queue.ToArray();for (int i = 0; i < array.Length; i++)
{Console.WriteLine(array[i]);
}//4.循环出列
while(queue.Count>0)
{object o = queue.Dequeue();Console.WriteLine(o);
}
Console.WriteLine(queue.Count);
装箱拆箱
由于用万物之父来存储数据,自然存在装箱拆箱。
当往其中进行值类型存储时就是在装箱
当将值类型对象取出来转换使用时,就存在拆箱。
队列的存储规则
先进先出
练习
使用队列存储消息,一次性存10条消息,每隔一段时间打印一条消息
控制台打印消息时要有明显停顿感
Hashtable散列表
Hashtable的本质
Hashtable(又称散列表) 是基于键的哈希代码组织起来的 键/ 值对
它的主要作用是提高数据查询的效率
使用键来访问集合中的元素
//需要引用命名空间 System.Collections
Hashtable hashtable = new Hashtable();
增删查改
增
hashtable.Add(1, "123");hashtable.Add("123", 2);hashtable.Add(true, false);hashtable.Add(false, false);//注意:不能出现相同键
删
//1.只能通过键去删除hashtable.Remove(1);//2.删除不存在的键 没反应hashtable.Remove(2);//3.或者直接清空hashtable.Clear();
查
//1.通过键查看值
// 找不到会返回空
Console.WriteLine(hashtable[1]);
Console.WriteLine(hashtable[4]);//null
Console.WriteLine(hashtable["123123"]);//2.查看是否存在
//根据键检测
if( hashtable.Contains(2) )
{Console.WriteLine("存在键为2的键值对");
}if( hashtable.ContainsKey(2) )
{Console.WriteLine("存在键为2的键值对");
}//根据值检测
if( hashtable.ContainsValue(12) )
{Console.WriteLine("存在值为12的键值对");
}
改
//只能改 键对应的值内容 无法修改键
Console.WriteLine(hashtable[1]);
hashtable[1] = 100.5f;
Console.WriteLine(hashtable[1]);
遍历
//得到键值对 数量
Console.WriteLine(hashtable.Count);//1.遍历所有键
foreach (object item in hashtable.Keys)
{Console.WriteLine("键:"+item);Console.WriteLine("值:"+hashtable[item]);
}//2.遍历所有值
foreach (object item in hashtable.Values)
{Console.WriteLine("值:" + item);
}//3.键值对一起遍历
foreach (DictionaryEntry item in hashtable)
{Console.WriteLine("键:" + item.Key + "值:" + item.Value);
}//4.迭代器遍历法
IDictionaryEnumerator myEnumerator = hashtable.GetEnumerator();
bool flag = myEnumerator.MoveNext();
while (flag)
{Console.WriteLine("键:" + myEnumerator.Key + "值:" + myEnumerator.Value);flag = myEnumerator.MoveNext();
}
装箱拆箱
由于用万物之父来存储数据,自然存在装箱拆箱
当往其中进行值类型存储时就是在装箱
当将值类型对象取出来转换使用时,就存在拆箱
Hashtable的存储规则
一个键值对形式存储的 容器
一个键 对应一个值
类型是object
练习
制作一个怪物管理器,提供创建怪物
移除怪物的方法。每个怪物都有自己的唯一ID
泛型
泛型是什么
泛型实现了类型参数化,达到代码重用目的
通过类型参数化来实现同一份代码上操作多种类型
泛型相当于类型占位符
定义类或方法时使用替代符代表变量类型
当真正使用类或者方法时再具体指定类型
泛型分类
泛型类和泛型接口
基本语法:
class 类名<泛型占位字母>
interface 接口名<泛型占位字母>
class A<T>
{public T Value;
}interface B<T>
{T Value{get;set;}
}
泛型函数
基本语法:函数名<泛型占位字母>(参数列表)
注意:泛型占位字母可以有多个,用逗号分开
泛型方法
- 普通类中的泛型方法
class Test2
{public void TestFun<T>( T value){Console.WriteLine(value);}public void TestFun<T>(){//用泛型类型 在里面做一些逻辑处理,default不管T是什么类型都会得到默认值T t = default(T);}public T TestFun<T>(string v){return default(T);}public void TestFun<T,K,M>(T t, K k, M m){}
}
- 泛型类中的泛型方法
//虽然和前面的类名一样,但是是不同的类,因为这里泛型属于类的一部分
class Test2<T>{public T value;public void TestFun<K>(K k){Console.WriteLine(k);}//这个不叫泛型方法 因为 T是泛型类申明的时候 就指定 在使用这个函数的时候 //我们不能再去动态的变化了public void TestFun(T t){}}
泛型的作用
-
不同类型对象的相同逻辑处理就可以选择泛型
-
使用泛型可以一定程度避免装箱拆箱
举例:优化ArrayList
class ArrayList<T>
{private T[] array;public void Add(T value){}public void Remove( T value){}
}
1.申明泛型时 它只是一个类型的占位符
2.泛型真正起作用的时候 是在使用它的时候
3.泛型占位字母可以有n个用逗号分开
4.泛型占位字母一般是大写字母
5.不确定泛型类型时 获取默认值 可以使用default(占位字符)
6.看到<> 包裹的字母 那肯定是泛型
练习题
定义一个泛型方法,方法内判断该类型为何类型,并返回类型的名称与占有的字节数
如果是int,则返回“整形,4字节”
只考虑以下类型
int:整形
char:字符
float:单精度浮点数
string:字符串
如果是其它类型,则返回“其它类型”
(可以通过typeof(类型) == typeof(类型)的方式进行类型判断)
泛型约束
什么是泛型约束
让泛型的类型有一定的限制
关键字:where
泛型约束一共有6种
1.值类型 where 泛型字母:struct
2.引用类型 where 泛型字母:class
3.存在无参公共构造函数 where 泛型字母:new ()
4.某个类本身或者其派生类 where 泛型字母:类名
5.某个接口的派生类型 where 泛型字母:接口名
6.另一个泛型类型本身或者派生类型 where 泛型字母:另一个泛型字母where 泛型字母:(约束的类型)
各泛型约束讲解
值类型约束
class Test1<T> where T:struct
{public T value;public void TestFun<K>(K v) where K:struct{}
}
引用类型约束
class Test2<T> where T:class
{public T value;public void TestFun<K>(K k) where K:class{}
}
存在无参公共构造函数
class Test3<T> where T:new()
{public T value;public void TestFun<K>(K k) where K : new(){}
}
class Test1
{public Test1(){}
}class Test2
{public Test2(int a){}
}Test3<Test1> a = new Test3<Test1>();
类约束
class Test4<T> where T : Test1{public T value;public void TestFun<K>(K k) where K : Test1{}}class Test3:Test1{}
接口约束
interface IFly
{}interface IMove:IFly
{}class Test4:IFly
{}class Test5<T> where T : IFly
{public T value;public void TestFun<K>(K k) where K : IFly{}
}
另一个泛型约束
class Test6<T, U> where T : U
{public T value;public void TestFun<K,V>(K k) where K : V{}
}Test6<Test4, IFly> t6 = new Test6<Test4, IFly>();
约束的组合使用
class Test7<T> where T: class,new(){}
多个泛型有约束
class Test8<T,K> where T:class,new() where K:struct{}
泛型约束:让类型有一定限制
class
struct
new ()
类名
接口名
另一个泛型字母注意:
1.可以组合使用
2.多个泛型约束 用where连接即可
练习
- 用泛型实现一个单例模式基类
- 利用泛型知识点,仿造ArrayList实现一个不确定数组类型的类
实现增删查改方法
List
List是一个C#为我们封装好的类,
它的本质是一个可变类型的泛型数组,
List类帮助我们实现了很多方法,
比如泛型数组的增删查改
//需要引用命名空间
//using System.Collections.Generic
List<int> list = new List<int>();
List<string> list2 = new List<string>();
List<bool> list3 = new List<bool>();
List<string> list5 = new List<string>();
增删查改
增
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);list2.Add("123");List<string> listStr = new List<string>();
listStr.Add("123");
list2.AddRange(listStr);list.Insert(0, 999);
Console.WriteLine(list[0]);
删
//1.移除指定元素
list.Remove(1);
//2.移除指定位置的元素
list.RemoveAt(0);
//3.清空
list.Clear();
查
//1.得到指定位置的元素
Console.WriteLine(list[0]);
//2.查看元素是否存在
if( list.Contains(1) )
{Console.WriteLine("存在元素 1");
}
//3.正向查找元素位置
// 找到返回位置 找不到 返回-1
int index = list.IndexOf(5);
Console.WriteLine(index);
//4.反向查找元素位置
// 找到返回位置 找不到 返回-1
index = list.LastIndexOf(2);
Console.WriteLine(index);
改
Console.WriteLine(list[0]);
list[0] = 99;
Console.WriteLine(list[0]);
遍历
//长度
Console.WriteLine(list.Count);
//容量
//避免产生垃圾
Console.WriteLine(list.Capacity);
Console.WriteLine("**********************");
for (int i = 0; i < list.Count; i++)
{Console.WriteLine(list[i]);
}
Console.WriteLine("**********************");
foreach (int item in list)
{Console.WriteLine(item);
}
List和ArrayList的区别
List内部封装的是一个泛型数组
ArrayList内部封装的是一个object数组
练习
-
建立一个整形List,为它添加10~1
删除List中第五个元素
遍历剩余元素并打印 -
一个Monster基类,Boss和Gablin类继承它。
在怪物类的构造函数中,将其存储到一个怪物List中
遍历列表可以让Boss和Gablin对象产生不同攻击
Dictionary
Dictionary的本质
可以将Dictionary理解为 拥有泛型的Hashtable
它也是基于键的哈希代码组织起来的 键/ 值对
键值对类型从Hashtable的object变为了可以自己制定的泛型
//需要引用命名空间 using System.Collections.Generic
Dictionary<int, string> dictionary = new Dictionary<int, string>();
增删查改
增
//注意:不能出现相同键
dictionary.Add(1, "123");
dictionary.Add(2, "222");
dictionary.Add(3, "222");dictionary.Add(4, "sss");
删
//1.只能通过键去删除
// 删除不存在键 没反应
dictionary.Remove(1);
dictionary.Remove(4);//2.清空
dictionary.Clear();
dictionary.Add(1, "123");
dictionary.Add(2, "222");
dictionary.Add(3, "222");
查
//1.通过键查看值
// 找不到直接报错
Console.WriteLine(dictionary[2]);
//Console.WriteLine(dictionary[4]);
Console.WriteLine(dictionary[1]);//2.查看是否存在
// 根据键检测
if( dictionary.ContainsKey(4) )
{Console.WriteLine("存在键为1的键值对");
}
// 根据值检测
if (dictionary.ContainsValue("1234"))
{Console.WriteLine("存在值为123的键值对");
}
改
Console.WriteLine(dictionary[1]);dictionary[1] = "555";Console.WriteLine(dictionary[1]);
遍历
Console.WriteLine("**************");
Console.WriteLine(dictionary.Count);
//1.遍历所有键
foreach (int item in dictionary.Keys)
{Console.WriteLine(item);Console.WriteLine(dictionary[item]);
}
//2.遍历所有值
Console.WriteLine("**************");
foreach (string item in dictionary.Values)
{Console.WriteLine(item);
}
//3.键值对一起遍历
Console.WriteLine("**************");
foreach (KeyValuePair<int,string> item in dictionary)
{Console.WriteLine("键:" + item.Key + "值:" + item.Value);
}
练习
-
使用字典存储0~9的数字对应的大写文字 提示用户输入一个不超过三位的数,提供一个方法,返回数的大写 例如:306,返回叁零陆
-
计算每个字母出现的次数“Welcome to Unity World!”,使用字典存储,最后遍历整个字典,不区分大小写
Dictionary<char, int> dic = new Dictionary<char, int>();
string str = "Welcome to Unity World!";
str = str.ToLower();
for (int i = 0; i < str.Length; i++)
{if( dic.ContainsKey(str[i]) ){dic[str[i]] += 1;}else{dic.Add(str[i], 1);}
}foreach (char item in dic.Keys)
{Console.WriteLine("字母{0}出现了{1}次", item, dic[item]);
}
顺序存储和链式存储
数据结构
数据结构是计算机存储、组织数据的方式(规则)
数据结构是指相互之间存在一种或多种特定关系的数据元素的集合
比如自定义的一个 类 也可以称为一种数据结构 自己定义的数据组合规则不要把数据结构想的太复杂
简单点理解,就是人定义的 存储数据 和 表示数据之间关系 的规则而已常用的数据结构(前辈总结和制定的一些经典规则)
数组、栈、队列、链表、树、图、堆、散列表
线性表
线性表是一种数据结构,是由n个具有相同特性的数据元素的有限序列
比如数组、ArrayList、Stack、Queue、链表等等
顺序存储和链式存储 是数据结构中两种 存储结构
顺序存储
数组、Stack、Queue、List、ArrayList —— 顺序存储
只是 数组、Stack、Queue的组织规则不同而已
顺序存储:
用一组地址连续的存储单元依次存储线性表的各个数据元素
链式存储
单向链表、双向链表、循环链表 —— 链式存储
链式存储(链接存储):
用一组任意的存储单元存储线性表中的各个数据元素
自己实现一个最简单的单向链表
/// <summary>
/// 单向链表节点
/// </summary>
/// <typeparam name="T"></typeparam>
class LinkedNode<T>
{public T value;//这个存储下一个元素是谁 相当于钩子public LinkedNode<T> nextNode;public LinkedNode(T value){this.value = value;}
}/// <summary>
/// 单向链表类 管理 节点 管理 添加等等
/// </summary>
/// <typeparam name="T"></typeparam>
class LindedList<T>
{public LinkedNode<T> head;public LinkedNode<T> last;public void Add(T value){//添加节点 必然是new一个新的节点LinkedNode<T> node = new LinkedNode<T>(value);if( head == null ){head = node;last = node;}else{last.nextNode = node;last = node;}}public void Remove(T value){if( head == null ){return;}if( head.value.Equals(value) ){head = head.nextNode;//如果头节点 被移除 发现头节点变空//证明只有一个节点 那尾也要清空if( head == null ){last = null;}return;}LinkedNode<T> node = head;while(node.nextNode != null){if( node.nextNode.value.Equals(value) ){//让当前找到的这个元素的 上一个节点//指向 自己的下一个节点node.nextNode = node.nextNode.nextNode;break;}}}
}
顺序存储和链式存储的优缺点
从增删查改的角度去思考
增:链式存储 计算上 优于顺序存储 (中间插入时链式不用像顺序一样去移动位置)
删:链式存储 计算上 优于顺序存储 (中间删除时链式不用像顺序一样去移动位置)
查:顺序存储 使用上 优于链式存储 (数组可以直接通过下标得到元素,链式需要遍历)
改:顺序存储 使用上 优于链式存储 (数组可以直接通过下标得到元素,链式需要遍历)
常用的数据结构有哪些
数组、栈、队列、链表、树、图、堆、散列表
顺序存储和链式存储的区别
顺序存储:内存中用一组地址连续的存储单元存储线性表(连续地址存储)
链式存储:内存中用一组任意的存储单元存储线性表(任意地址存储)
练习
请尝试自己实现一个双向链表
并提供以下方法和属性
数据的个数,头节点,尾节点
增加数据到链表最后
删除指定位置节点
LinkedList
LinkedList是一个C#为我们封装好的类
它的本质是一个可变类型的泛型双向链表
//需要引用命名空间//using System.Collections.GenericLinkedList<int> linkedList = new LinkedList<int>();LinkedList<string> linkedList2 = new LinkedList<string>();//链表对象 需要掌握两个类//一个是链表本身 一个是链表节点类LinkedListNode
增删查改
增
//1.在链表尾部添加元素linkedList.AddLast(10);//2.在链表头部添加元素linkedList.AddFirst(20);//3.在某一个节点之后添加一个节点// 要指定节点 先得得到一个节点LinkedListNode<int> n = linkedList.Find(20);//在n节点后面添加一个15的值的节点linkedList.AddAfter(n, 15);//4.在某一个节点之前添加一个节点// 要指定节点 先得得到一个节点linkedList.AddBefore(n, 11);
删
//1.移除头节点
linkedList.RemoveFirst();
//2.移除尾节点
linkedList.RemoveLast();
//3.移除指定节点
// 无法通过位置直接移除
linkedList.Remove(20);
//4.清空
linkedList.Clear();linkedList.AddLast(1);
linkedList.AddLast(2);
linkedList.AddLast(3);
linkedList.AddLast(4);
查
//1.头节点
LinkedListNode<int> first = linkedList.First;
//2.尾节点
LinkedListNode<int> last = linkedList.Last;
//3.找到指定值的节点
// 无法直接通过下标获取中间元素
// 只有遍历查找指定位置元素
LinkedListNode<int> node = linkedList.Find(3);
Console.WriteLine(node.Value);
node = linkedList.Find(5);
//4.判断是否存在
if( linkedList.Contains(1) )
{Console.WriteLine("链表中存在1");
}
改
//要先得再改 得到节点 再改变其中的值
Console.WriteLine(linkedList.First.Value);
linkedList.First.Value = 10;
Console.WriteLine(linkedList.First.Value);
遍历
//1.foreach遍历
foreach (int item in linkedList)
{Console.WriteLine(item);
}//2.通过节点遍历
// 从头到尾
Console.WriteLine("&&&&&&&&&&&&&&&&&&&&&&&&&&&");
LinkedListNode<int> nowNode = linkedList.First;
while (nowNode != null)
{Console.WriteLine(nowNode.Value);nowNode = nowNode.Next;
}// 从尾到头Console.WriteLine("&&&&&&&&&&&&&&&&&&&&&&&&&&&");
nowNode = linkedList.Last;
while (nowNode != null)
{Console.WriteLine(nowNode.Value);nowNode = nowNode.Previous;
}
练习
使用Linkedlist,向其中加入10个随机整形变量
正向遍历一次打印出信息
反向遍历一次打印出信息
数据容器
变量
无符号
byte ushort uint ulong
有符号
sbyte short int long
浮点数
float double decimal
特殊
char bool string
复杂数据容器
枚举 enum
结构体 struct
数组(一维、二维、交错) [] [,] [][]
类
数据集合
using System.Collections;ArrayList object数据列表
Stack 栈 先进后出
Queue 队列 先进先出
Hashtable 哈希表 键值对
泛型数据集合
using System.Collections.Generic;List 列表 泛型列表
Dictionary 字典 泛型哈希表
LinkedList 双向链表
Statck 泛型栈
Queue 泛型队列
泛型栈和队列
//命名空间:using System.Collections.Generic;
//使用上 和之前的Stack和Queue一模一样
Stack<int> stack = new Stack<int>();
Queue<object> queue = new Queue<object>();
如何使用数据容器
数组、List、Dictionary、Stack、Queue、LinkedList
这些存储容器,对于我们来说应该如何选择他们来使用
普通线性表:
数组,List,LinkedList
数组:固定的不变的一组数据
List: 经常改变,经常通过下标查找
LinkedList:不确定长度的,经常临时插入改变,查找不多先进后出:
Stack
对于一些可以利用先进后出存储特点的逻辑
比如:UI面板显隐规则先进先出:
Queue
对于一些可以利用先进先出存储特点的逻辑
比如:消息队列,有了就往里放,然后慢慢依次处理键值对:
Dictionary
需要频繁查找的,有对应关系的数据
比如一些数据存储 id对应数据内容
道具ID ——> 道具信息
怪物ID ——> 怪物对象
等等