C#【进阶】常用泛型数据结构类

常用泛型数据结构类

在这里插入图片描述

1、List

1、List的本质
List是C#封装好的类,本质是一个可变类型的泛型数组
2、声明
List<int> list1 = new List<int>();
List<string> list2 = new List<string>();
List<string> listStr = new List<string>();
3、增删查改
增
    list1.Add(11);
    list2.AddRange(listStr);
	list1.Insert(0,66);//1.移除指定元素
    list1.Remove(11);
    //2、移除指定位置元素
    list1.RemoveAt(0);
    //3、清空
    list1.Clear();//1、查看指定位置元素
    Console.WriteLine(list1[0]);
    //2、查看元素是否存在
    if (list1.Contains(11))
    {
        Console.WriteLine("存在");
    }
    //3、正向查找元素位置
    int index = list1.IndexOf(11);
    Console.WriteLine(index);
    //4、反向查找元素位置
    index = list1.LastIndexOf(11);
    Console.WriteLine(index);
改
    list1[0] = 22;
4、遍历
//长度
Console.WriteLine(list1.Count);
//容量
Console.WriteLine(list1.Capacity);
//for循环遍历
for (int i = 0; i < list1.Count; i++)
{
    Console.WriteLine(list1[i]);
}
//迭代器遍历
foreach (int i in list1)
{
    Console.WriteLine(i);
}
思考 存储基类类型列表
//一个Monster基类,Boss和Gablin类继承它
//在怪物类的构造函数中,将其存储到一个怪物List中
//遍历列表可以让Boss和Gablin对象产生不同攻击

Boss boss1 = new Boss();
Boss boss2 = new Boss();
Gablin Gablin1 = new Gablin();
Gablin Gablin2 = new Gablin();
for (int i = 0; i < Monster.monsters.Count; i++)
{
    Monster.monsters[i].Atk();
}
abstract class Monster
{
    public static List<Monster> monsters = new List<Monster>();
    public Monster()
    {
        monsters.Add(this);
    }
    public abstract void Atk();
}
class Gablin : Monster
{
    public override void Atk()
    {
        Console.WriteLine("哥布林的攻击");
    }
}
class Boss : Monster
{
    public override void Atk()
    {
        Console.WriteLine("Boss的攻击");
    }
}

2、Dictionary

1、Dictionary的本质
可以将Dictionary理解为:拥有泛型的Hashtable
它是基于键的哈希代码组织起来的键值对
键值对类型从Hashtable的object变为了可以自己指定的泛型
2、声明
Dictionary<int,string> dictionary = new Dictionary<int,string>();
3、增删查改
//不能出现相同名的键
    dictionary.Add(1, "aaa");
    dictionary.Add(2, "bbb");
    dictionary.Add(3, "ccc");//1、只能通过键去删除
    dictionary.Remove(3);
    //2、清空
    dictionary.Clear();//1、通过键查看值,键找不到报错
    Console.WriteLine(dictionary[2]);
    //2、查看是否存在
    //根据键检测
    if (dictionary.ContainsKey(2))
    {
        Console.WriteLine("存在");
    }
    //根据值检测
    if (dictionary.ContainsValue("bbb"))
    {
        Console.WriteLine("存在");
    }
改
    dictionary[1]="666";
4、遍历
1、遍历所有键
    foreach (int item in dictionary.Keys)
    {
        Console.WriteLine(item);
        Console.WriteLine(dictionary[item]);
    }
2、遍历所有值
    foreach(string item in dictionary.Values)
    {
        Console.WriteLine(item);
    }
3、键值对遍历
    foreach(KeyValuePair<int,string> pair in dictionary)
    {
        Console.WriteLine(pair);
    }
思考1 数字对应的大写
//使用字典存储0~9的数字对应的大写文字
//提示用户输入一个不超过三位的数,提供一个方法,返回数的大写
try
{
    Console.WriteLine("输入三位数");
    Console.WriteLine(GetInfo(int.Parse(Console.ReadLine())));
}
catch
{

    Console.WriteLine("wrong");
}

string GetInfo(int num)
{
    Dictionary<int, string> dictionary = new Dictionary<int, string>();
    dictionary.Add(0, "零");
    dictionary.Add(1, "壹");
    dictionary.Add(2, "贰");
    dictionary.Add(3, "叁");
    dictionary.Add(4, "肆");
    dictionary.Add(5, "伍");
    dictionary.Add(6, "陆");
    dictionary.Add(7, "柒");
    dictionary.Add(8, "捌");
    dictionary.Add(9, "玖");
    int b = num / 100;
    string str = "";
    if (b != 0)
    {
        str += dictionary[b];
    }

    int s = num % 100 / 10;
    if (s != 0 || str != "")
    {
        str += dictionary[s];
    }

    int g = num % 10;
    str += dictionary[g];
    return str;
}
思考 2 字母出现的次数
//计算每个字母出现的次数“Welcome to Unity World!”,使用字典存储,最后遍历,不区分大小写
Dictionary<char,int> dictionary = new Dictionary<char,int>();
string str = "Welcome to Unity World!";
str = str.ToLower();
for (int i = 0; i < str.Length; i++)
{
    if (dictionary.ContainsKey(str[i]))
    {
        dictionary[str[i]]++;
    }
    else
    {
        dictionary.Add(str[i], 1);
    }
}
foreach (char c in dictionary.Keys)
{
    Console.WriteLine("{0}出现了{1}次", c, dictionary[c]);
}

3、顺序存储和链式存储

1、数据结构
数据结构是计算机存储、组织数据的规则
数据结构是指相互之间存在一种或多种特定关系的数据元素的集合
存储数据和表示数据之间关系的规则
常用的数据结构
数组、栈、队列、链表、树、图、堆、散列表
2、线性表
线性表是一种数据结构,是由n个具有相同特性的数据元素的有限序列
例如:数组、ArrayList、Stack、Queue、链表
3、顺序存储

顺序存储和链式存储是数据结构中两种存储结构

数组、Stack、Queue、List、ArrayList 顺序存储
数组、Stack、Queue的组织规则不同
顺序存储:用一组地址连续的存储单元依次存储线性表的各个数据元素
4、链式存储
单向链表、双向链表、循环链表	链式存储
链式存储(链接存储):用一组任意的存储单元存储线性表中的各个数据元素
5、自己实现一个最简单的单向链表
LinkedList<int> link = new LinkedList<int>();
link.Add(1);
link.Add(2);
link.Add(3);
link.Add(4);

LinkedNode<int> node = link.head;
while (node != null)
{
    Console.WriteLine(node.value);
    node = node.nextNode;
}

link.Remove(2);
node = link.head;
while (node != null)
{
    Console.WriteLine(node.value);
    node = node.nextNode;
}

link.Add(5);
node = link.head;
while (node != null)
{
    Console.WriteLine(node.value);
    node = node.nextNode;
}
/// <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 LinkedList<T>
{
    public LinkedNode<T> head;
    public LinkedNode<T> last;
    public void Add(T value)
    {
        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;
            }
            node = node.nextNode;
        }
    }
}
6、顺序存储和链式存储的优缺点
增、删:链式存储优于顺序存储
查、改:顺序存储优于链式存储
思考 双向链表
//实现一个双向链表,并提供以下方法和属性
//数据的个数,头节点,尾节点
//增加数据到链表最后
//删除指定位置节点

LinkedList<int> link = new LinkedList<int>();
link.Add(2);
link.Add(3);
link.Add(4);
link.Add(5);
//正向访问
LinkedNode<int> node = link.Head;
while (node != null)
{
    Console.WriteLine(node.value);
    node = node.nextNode;
}

link.RemoveAt(5);

//反向访问
node = link.Last;
while (node != null)
{
    Console.WriteLine(node.value);
    node = node.frontNode;
}

class LinkedNode<T>
{
    public T value;
    public LinkedNode<T> frontNode;
    public LinkedNode<T> nextNode;

    public LinkedNode(T value)
    {
        this.value = value;
    }
}

class LinkedList<T>
{
    private int count;
    private LinkedNode<T> head;
    private LinkedNode<T> last;
    
    public int Count
    {
        get { return count; }
    }

    public LinkedNode<T> Head
    {
        get { return head; }
    }

    public LinkedNode<T> Last
    {
        get { return last; }
    }

    //添加
    public void Add(T value)
    {
        LinkedNode<T> node = new LinkedNode<T>(value);
        if (head == null)
        {
            head = node;
            last = node;
        }
        else
        {
            //添加到尾部
            last.nextNode = node;
            //尾部添加的节点 记录自己的上一个节点
            node.frontNode = last;

            //将新加节点记录为last
            last = node;
        }
        count++;
    }

    //删除
    public void RemoveAt(int index)
    {
        if (index >= count || index < 0)
        {
            Console.WriteLine("删除失败");
            return;
        }
        int tempCount = 0;
        LinkedNode<T> tempNode = head;
        while (true)
        {
            //计数找到对应节点
            if (tempCount == index)
            {
                //移除节点
                if (tempNode.frontNode !=null)
                {
                    tempNode.frontNode.nextNode = tempNode.nextNode;
                }
                if (tempNode.nextNode != null)
                {
                    tempNode.nextNode.frontNode = tempNode.frontNode;
                }
                //若移除了头节点,则将头指向下一个节点
                if (index == 0)
                {
                    head = head.nextNode;
                }
                //将倒数第二个作为尾节点
                else if (index == count-1)
                {
                    last = last.frontNode;
                }
                count--;
                break;           
            }
            //每次下移一位
            tempNode = tempNode.nextNode;
            tempCount++;
        }
    }
}

4、Linkedlist

1、LinkedList
LinkedList是一个C#为我们封装好的类
它的本质是一个可变类型的泛型双向链表
2、声明
//链表LinkedList 链表节点类LinkedListNode
LinkedList<int> link = new LinkedList<int>();
LinkedList<string> link2 = new LinkedList<string>();
3、增删查改
LinkedList<int> link = new LinkedList<int>();1、在链表头部添加元素
    	link.AddFirst(1);
    2、在链表尾部添加元素
		link.AddLast(20);
    3、在某个节点之前添加元素
		LinkedListNode<int> c = link.Find(2);
		link.AddBefore(c, 19);
    4、在某个节点之后添加元素
		link.AddAfter(c, 21);1、移除头节点
    	link.RemoveFirst();
    2、移除尾节点
    	link.RemoveLast();
    3、移除指定节点
        link.Remove(20);1、头节点
    	LinkedListNode<int> first = link.First;
    2、尾节点
        LinkedListNode<int> last = link.Last;
    3、找到指定值节点
    	LinkedListNode<int> node = link.Find(20);
		Console.WriteLine(node.Value);
    4、判断是否存在
        if (link.Contains(20))
        {
            Console.WriteLine("存在");
        }
改
    先得到节点,再该值
    	link.First.Value = 10;
4、遍历
1、foreach遍历
	foreach (int i in link)
    {
        Console.WriteLine(i);
    }
2、通过节点遍历
    从头到尾
    	LinkedListNode<int> nowNode = link.First;
        while (nowNode != null)
        {
            Console.WriteLine(nowNode.Value);
            nowNode = nowNode.Next;
        }
    从尾到头
        nowNode = link.Last;
        while (nowNode != null)
        {
            Console.WriteLine(nowNode.Value);
            nowNode = nowNode.Previous;
        }

5、泛型栈和队列

Stack<int> s = new Stack<int>();
Queue<int> q = new Queue<int>();

总结 数据用法

普通线性表:
    数组、List、LinkedList
        ArrayList:固定的不变的一组数据
        List:经常改变,经常通过下标查找
        LinkedList:不确定长度,经常临时插入改变,查找次数少

先进后出
    Stack
    对于一些可以利用先进后出存储特点的逻辑
    比如:UI面板显隐规则

先进先出
    Queue
    对于一些可以利用先进先出存储特点的逻辑
    比如:消息队列,实时存放,慢慢依次处理

键值对
    Dictionary
    需要频繁查找的,有对应关系的数据
    比如一些数据存储,id对应数据内容
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值