自学内容网 自学内容网

C#学习记录--更新中

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);
#endregion

if (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和数组的区别

  1. ArrayList可以不用一开始就是定长的,而数组是定长的
  2. ArrayList默认是object类型,而数组可以指定存储类型
  3. ArrayList封装了很多增删查改API,而数组需要自己实现
  4. ArrayList使用时候存在装箱拆箱,而数组只要使用时候不是object数组就不存在这个问题
  5. 数组长度为Length,ArrayList长度为Count,容量为Capecity

ArrayList和List的区别

  1. ArrayList 不带泛型 数据类型丢失,而List 带泛型 数据类型不丢失
  2. ArrayList 需要装箱拆箱 List不需要
  3. 在声明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;
    }
}

泛型函数
基本语法:函数名<泛型占位字母>(参数列表)
注意:泛型占位字母可以有多个,用逗号分开

泛型方法

  1. 普通类中的泛型方法
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)
    {

    }
}
  1. 泛型类中的泛型方法
//虽然和前面的类名一样,但是是不同的类,因为这里泛型属于类的一部分 
class Test2<T>
 {
     public T value;

     public void TestFun<K>(K k)
     {
         Console.WriteLine(k);
     }

     //这个不叫泛型方法 因为 T是泛型类申明的时候 就指定 在使用这个函数的时候 
     //我们不能再去动态的变化了
     public void TestFun(T t)
     {

     }
 }

泛型的作用

  1. 不同类型对象的相同逻辑处理就可以选择泛型

  2. 使用泛型可以一定程度避免装箱拆箱
    举例:优化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连接即可

练习

  1. 用泛型实现一个单例模式基类
  2. 利用泛型知识点,仿造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数组

练习

  1. 建立一个整形List,为它添加10~1
    删除List中第五个元素
    遍历剩余元素并打印

  2. 一个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);
}

练习

  1. 使用字典存储0~9的数字对应的大写文字
    提示用户输入一个不超过三位的数,提供一个方法,返回数的大写
    例如:306,返回叁零陆
    
  2. 计算每个字母出现的次数“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.Generic
 LinkedList<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 ——> 怪物对象
等等

原文地址:https://blog.csdn.net/2301_76618920/article/details/143582124

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!