C#学习记录--更新中

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);
#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 ——> 怪物对象
等等

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/910254.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【The Art of Unit Testing 3_自学笔记06】3.4 + 3.5 单元测试核心技能之:函数式注入与模块化注入的解决方案简介

文章目录 3.4 函数式依赖注入技术 Functional injection techniques3.5 模块化依赖注入技术 Modular injection techniques 写在前面 上一篇的最后部分对第三章后续内容做了一个概括性的梳理&#xff0c;并给出了断开依赖项的最简单的实现方案&#xff0c;函数参数值注入法。本…

如何打开别人的 vsqt 代码?QString 中有中文的时候,如何转换中文?

如何打开别人的 vsqt 代码&#xff1f; 我们下载了 一段源码。并且知道这个源码的关于 音视频的&#xff0c;那么八成会用到ffmpeg 假设我们源码下载后&#xff0c;位置在D:\downloadcode\112_yuv_rgb_player 第一步就是删除.vs 和debug&#xff0c;因为这是别人的vs 项目的…

AI 驱动的 SIEM 对增强安全性的 9 大好处

作者&#xff1a;来自 Elastic Joe DeFever 与传统的 SIEM 解决方案相比&#xff0c;人工智能驱动的安全信息和事件管理 (security information and event management - ) 解决方案使从业人员能够更高效、更有效地工作&#xff0c;而传统的 SIEM 解决方案依赖于手动流程来配置数…

基于Python的影院电影购票系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

深度学习经典模型之ZFNet

1 ZFNet 1.1 模型介绍 ​ ZFNet是由 M a t t h e w Matthew Matthew D . Z e i l e r D. Zeiler D.Zeiler和 R o b Rob Rob F e r g u s Fergus Fergus在AlexNet基础上提出的大型卷积网络&#xff0c;在2013年ILSVRC图像分类竞赛中以11.19%的错误率获得冠军&#xff08;实际…

ES8388 —— 带耳机放大器的低功耗立体声音频编解码器(4)

接前一篇文章&#xff1a;ES8388 —— 带耳机放大器的低功耗立体声音频编解码器&#xff08;3&#xff09; 二、详细描述 5. 微控制器配置接口 该设备支持标准SPI和2线&#xff08;I2C&#xff09;微控制器配置接口。外部微控制器可以通过写入内部配置寄存器来完全配置设备。…

Python实例:爱心代码

前言 在编程的奇妙世界里,代码不仅仅是冰冷的指令集合,它还可以成为表达情感、传递温暖的独特方式。今天,我们将一同探索用 Python 语言绘制爱心的神奇之旅。 爱心,这个象征着爱与温暖的符号,一直以来都在人类的情感世界中占据着特殊的地位。而通过 Python 的强大功能,…

部署stable-diffusion3.5 大模型,文生图

UI 使用推荐的ComfyUI&#xff0c;GitHub 地址&#xff0c;huggingface 需要注册登录&#xff0c;需要下载的文件下面有说明 Dockerfile 文件如下&#xff1a; FROM nvidia/cuda:12.4.0-base-ubuntu22.04 RUN apt-get update && apt-get install python3 pip git --n…

glibc 内存分配与释放机制详解

作者&#xff1a;来自 vivo 互联网存储团队- Wang Yuzhi 本文以一次线上故障为基础介绍了使用 glibc 进行内存管理可能碰到问题&#xff0c;进而对库中内存分配与释放机制进行分析&#xff0c;最后提供了相应问题的解决方案。 一、引言 内存对象的分配与释放一直是后端开发人…

SpringBoot框架在城镇住房保障中的应用

3系统分析 3.1可行性分析 通过对本城镇保障性住房管理系统实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本城镇保障性住房管理系统采用SSM框架&#xff0c;JA…

Openlayers高级交互(20/20):超级数据聚合,页面不再混乱

本示例在vue+openlayers中使用cluster生成聚合数据的效果。在OpenLayers中实现点聚合(clustering)是一个常见的需求,特别是在处理大量地理数据点时。聚合可以提高地图的性能并减少视觉上的混乱。 一、示例效果图 专栏名称内容介绍Openlayers基础实战 (72篇)专栏提供73篇文…

内网渗透-信息收集篇

通过webshell或其他方式拿下一台机器&#xff0c;并且存在内网环境&#xff0c;这个时候就在准备进行内网渗透&#xff0c;而在内网渗透之前需要对本地机器进行信息收集&#xff0c;才能够更好的进行内网渗透。 目录 Windows本地基础信息收集 权限查看 判断域存在 查看防火…

诗林工作室(编号:mb0005)分享:HTML模版Paxton,一款自适应响应式图集、博客设计开发模板

这是来自国外一款HTML网页模板&#xff0c;适合Web开发人员做前端站点设计参考使用。全站模版倾向于图集、博客等多行业的平台模版开发。此模版适合各大CMS的主题模版开发参考&#xff0c;如常见的Wordpress主题开发、Z-Blog模板开发、Typecho模板开发、DiscuzX模板开发、Jooml…

SSLHandshakeException错误解决方案

1、错误提示 调用Http工具报如下异常信息&#xff1a; cn.hutool.core.io.IORuntimeException: SSLHandshakeException: Received fatal alert: handshake_failure2、查询问题 一开始我以为是代码bug&#xff0c;网络bug甚至是配置环境未生效&#xff0c;找了一大圈&#xf…

VBA07-方法

一、方法的定义 方法指对象所能执行的动作&#xff0c;它是一个动词。 二、方法的表达方式 三、关于工作簿的方法操作 3-1、新增一个工作簿 示例1&#xff1a; 此时&#xff0c;新增的工作簿的名字是系统默认的。 示例2&#xff1a; 【注意】&#xff1a; 当你尝试将工作簿…

MyBatis3-获取参数值的方式、查询功能及特殊SQL执行

目录 准备工作 获取参数值的方式&#xff08;重点&#xff09; 查询功能 查询一个实体类对象 查询一个list集合 查询单个数据 查询一条数据为map集合 查询多条数据为map集合 特殊SQL执行 模糊查询 批量删除 动态设置表名 添加功能获取自增的主键 准备工作 模块My…

构建基于 DCGM-Exporter, Node exporter,PROMETHEUS 和 GRAFANA 构建算力监控系统

目录 引言工具作用概述DCGM-ExporterNode exporterPROMETHEUSGRAFANA小结 部署单容器DCGM-ExporterNode exporterPROMETHEUSGRAFANANode exporterDCGM-Exporter 多容器Node exporterDCGM-ExporterDocker Compose 参考 引言 本文的是适用对象&#xff0c;是希望通过完全基于Doc…

基因组学与个性化健康:精准医疗的未来方向

基因组学&#xff08;Genomics&#xff09;是指对基因组&#xff0c;即一个生物体的全部基因和遗传信息进行分析和研究的科学&#xff0c;旨在探索基因在生物体中的功能、相互作用及其对健康和疾病的影响。个性化健康&#xff08;Personalized Health&#xff09;则是基于个体的…

阅读个位数?1分钟学会用AI做爆款,轻松涨粉不是梦

从去年开始&#xff0c;AI造就的视觉艺术就在各个平台上疯狂蔓延&#xff0c;人类用AI一年生成的内容&#xff0c;比过往几千年加起来都多。 网络上铺天盖地都是搞AI&#xff0c;但大部分人真的是在搞AI吗&#xff1f;并不尽然&#xff0c;大部分人只是想用AI搞钱。 更多实操…

发现 API 的 5 种方法

在处理目标时&#xff0c;最值得测试的部分是其 API。API 是动态的&#xff0c;它们比应用程序的其他部分更新得更频繁&#xff0c;并且负责许多后端繁重的工作。在现代应用程序中&#xff0c;我们通常会看到 REST API&#xff0c;但也会看到其他形式&#xff0c;例如 GraphQL …