1.自己实习find功能

        // Array.Find()
        int[] ages = new int[] {1,2,3,4,5};
        // Console.WriteLine(ages[10]); //System.IndexOutOfRangeException: 索引超出了数组界限。
        //调用自己的Find方法
        //参数1:整型的数组
        //参数2:func类型的函数  v => v % 2 == 0
        //  Console.WriteLine(MyArray.Find(ages, v => v % 2 == 0));


        //DivideByZeroException: 尝试除以零。
        //int a = 10;
        //Console.WriteLine(a/0);

        Console.WriteLine(MyArray.Find(ages, v => v % 2 == 0));
        Console.WriteLine(MyArray.Find(ages, v => v % 3 == 0));
    }
}
public class MyArray
{
    //arr 就是 int[] ages = new int[] { 1, 2, 3 };
    //match 就是  v => v % 2 == 0   函数必须调用
    public static int Find(int[] arr, Func<int, bool> match) //match 函数, 必须调用
    {
        if (arr == null)
        {
            throw new ArgumentNullException("array");
        }
        if (match == null)
        {
            throw new ArgumentNullException("match");
        }

        for (int i = 0; i < arr.Length; i++) //遍历每一个元素,判断元素是否满足match函数
        {
            if (match(arr[i]))  // 调用v => v % 2 == 0函数 ,v就是arr【i】 就是每一个元素
            {
                return arr[i];//返回元素本身
            }

        }

        return 0; //没找到话 返回默认值0
    }

2.冒泡排序

//冒泡排序,Bubble Sort   一个简单且常用的排序算法。因最大或最小的元素会经过交换慢慢出现在数列顶端,好似元素冒出来一样,得名“冒泡排序”。

//原理

//1. * *比较相邻元素 * *:从列表的第一个元素开始,比较相邻的两个元素
//2. * *交换位置 * *:如果前一个元素比后一个元素大(升序排序时),就交换它们的位置
//3. * *重复遍历 * *:对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对
//4. * *最大元素沉底 * *:每次完整遍历后,最大的元素会"冒泡"到列表的末尾
//5. * *缩小范围 * *:忽略已经排序好的末尾部分,重复上述过程
//6. * *完成排序 * *:当没有元素需要交换时,排序完成

int[] num = { 1, 2, 3,10, 5, 7, 8, 33, 9 };
//未优化
//外循环的循环次数0开始到长度为止,
//取出数组每一个元素
for (int i = 0; i < num.Length; i++)
{
    //内循环控制比较次数,最大次数减1
    //假设9个数,比较8次
    for (global::System.Int32 j = 0; j < num.Length-1; j++)
    {
        //ints1.Length===9  j最大 是 8   但是 j+1==9  索引越界
        if (num[j] > num[j+1]) //num[j]前面数; num[j+1]后面的数
        {
            //交换位置
            (num[j], num[j+1]) = (num[j+1], num[j]);
        }
    }
}
Console.WriteLine(string.Join("-",num));

//优化版
for (int i = 0; i < num.Length; i++)
{
    //-1的原因:  ints1.Length===8  j最大 是 7   但是 j+1==8  索引越界
    //-i的原因 : 每次循环都会多一组排序好的值,让内层循环每执行一次,就少一次
    for (int j = 0; j < num.Length - 1 - i; j++)
    {

        if (num[j] > num[j + 1])
        {
            //语法糖交换位置
            (num[j], num[j + 1]) = (num[j + 1], num[j]);
        }
    }
}
Console.WriteLine(string.Join("-", num));

3.选择排序

 /*
 int[] nums = { 1, 2, 30, 4, 5, 8, 8, 8, 9 };
 for (int i = 0; i < nums.Length; i++)
 {
     int minIndex = i;// 目前最小值的索引的i, 例如i=0
     for (int j   = i+1; j < nums.Length; j++)
     {
         if (nums[j] < nums[minIndex]) //  nums[minIndex] 最小值 ;nums[j]数组里面后面元素
                                       //nums[j]是小值 把小值的索引值赋值给minIndex
         {
             minIndex = j;
         }
     }

     if (minIndex!=i)
     {
         //交换位置nums[minIndex]
         (nums[i], nums[minIndex]) = (nums[minIndex], nums[i]);
     }
    
 }
 Console.WriteLine( string.Join("-",nums));
 */
 int[] nums = { 1, 2, 30, 4, 5, 8, 8, 8, 9 };
 // Array.Sort(nums);// 默认的是升序排序, 从小到大的排序
 //Array.Reverse(nums);// 颠倒数组的元素的顺序
 //Console.WriteLine(string.Join("-", nums));


 //第二种排序写法
 //Array.Sort(nums, (x, y) => { return x - y; });//升序排序
 //Console.WriteLine(string.Join("-", nums));

 //Array.Sort(nums, (x, y) => { return y - x; });//降序排序
 //Console.WriteLine(string.Join("-", nums));

 //第三种排序写法

 Array.Sort(nums, (x, y) =>
 {
     if (x < y) return -1;   // x 比 y 小 → x 放前面
     if (x > y) return 1;    // x 比 y 大 → x 放后面
     return 0;               // 相等 → 不动
 });
 Console.WriteLine(string.Join("-", nums));

4.ArrayList动态集合

//理解
//ArrayList实现了IList, ICollection, IEnumerable, ICloneable接口
//IList:List列表,主要负责集合的插入,添加,删除,取索引,判断是否包含某个项等操作。
//ICollection:Collection集合。主要负责集合中的项的个数,集合的复制,拷贝等。
//IEnumerable:Enumerable可枚举的; 可数的,可枚举的。主要实现迭代器,实现此接口类都可以被循环,被遍历,被迭代,被枚举
// ICloneable:Cloneable克隆,主要负责集合的克隆(复制,拷贝),了解和ICollection接口中CopyTo()的区别:https://blog.csdn.net/yao_hou/article/details/134484811

int[] ages = new int[] {1,2,3,4,5};

//ArrayList直接继承object
//int[] 继承于Array 继承于Object

//区别 :1ArrayList定义完之后数组的长度可以动态添加 ,int[]一旦定义完之后 长度是固定的,
//2 ArrayList存储的是对象类型,                       int[]数组只能存储相同类型的数据
//3 ArrayList存取数据出现装箱、拆箱操作,             int[] 不用装箱和拆箱
//4 ArrayList存储数据类型不安全,                     int[]数据类型安全
ArrayList list = new ArrayList() { 1, 2, 3, true, "ss", new object() };
Console.WriteLine(list.GetType().BaseType);//System.Object

ArrayList list1 = new ArrayList(); //创建一个动态集合对象

//1添加元素  把1转成对象类型之后 再添加到动态集合里面,
//把值类型转成引用类型的过程,就是装箱操作
list1.Add(1);
list1.Add(2);
list1.Add(3);

//3 AddRange() 添加一个范围 可以添加一个数组类型的数据. 也可以添加一个集合类型数据
// list1.AddRange(ages);
// list1.AddRange(list);


//2取出元素 通过索引值取出元素值 
Console.WriteLine(list1[0]);//1
//list1[0]本身一个对象,需要转成值类型,这个过程就是拆箱
Console.WriteLine((int)list1[0]);

//4 Contains 是否包含某个元素
Console.WriteLine(list1.Contains(1));//true

//5  IndexOf() 获取某个元素的索引值
Console.WriteLine(list1.IndexOf(1));

// 6 remove() 移除指定元素
list1.Remove(1);

//RemoveAt移除指定位置的元素
list1.RemoveAt(0);

//7 修改
list1[0] = "张三";

//8 Insert()在指定位置添加一个元素
list1.Insert(0, "李四");
//在指定位置添加一个范围数据
list1.InsertRange(2, ages);


//9清空集合
//list1.Clear();

//10LastIndexOf 找索引值 从后往前找
Console.WriteLine(list1.LastIndexOf("李四"));
//11 颠倒数组的元素
// list1.Reverse();

//12 GetRange 从源集合取出一个子集, 参数1从指定位置开始,参数2截取的长度
ArrayList list2 = list1.GetRange(0, 3);
// getRange() 不是独立列表 是原列表的试图,通过setRange修改原列表,再去遍历子列表会报错
// setRange()设置指定范围的数据
list1.SetRange(0, new int[] { 9999, 888 }); //基础列表中的该范围无效。一个可能的原因是元素被移除。

//如果添加list1.SetRange()这一句 ,下面的for出现报错
//foreach (var item in list2)
//{
//    Console.WriteLine(item+"??????");
//}




//for遍历
//list1.Count 集合数据个数
//for (int i = 0; i < list1.Count; i++)
//{
//    Console.WriteLine(list1[i]);
//}

foreach (var item in list1)
{
    Console.WriteLine(item + "------");
}

5.泛型集合

 //List<>:泛型集合,可以传入类型存储相同类型的数据,不存在装箱或者拆箱的过程
 List<int> list = new List<int>();
 List<string> list1 = new List<string> { "李张三", "李四" };
 Console.WriteLine(list1.Count);//个数

 //1添加元素
 list1.Add("1");
 list1.AddRange(new List<string> { "王五" });

 //2 移除指定元素
 //list1.Remove("1") ;
 //list1.RemoveAt(0) ;//移除指定位置的元素
 //RemoveAll() 移除指定条件的元素 返回值移除个数
 //Console.WriteLine(list1.RemoveAll(v => v.StartsWith("李")));

 // 3 修改通过索引值进行修改
 list1[2] = "焦恩俊";

 //4 插入
 list1.Insert(4, "何家劲");

 //list1.IndexOf("1") ; // 获取指定元素的索引值

 //List里面的高阶函数和数组当中高阶函数大部分都一样,只不过数组采用类名调用,List采用的是对象调用
 //list1.ForEach(x => Console.WriteLine(x));
 //list1.Contains() 是否包含元素


 foreach (var i in list1)
 {
     Console.WriteLine(i + "-------");
 }

6.字典

//字典: Dictionary<>,包含键(key)值(value)对.
//key键是唯一的,类似于数组的下标,数组下标只能整型,但是key可以任意类型
//value值是根据键去取

//定义一个字典
//int 是键的类型
//string 值的类型
Dictionary<int, string> dic = new Dictionary<int, string>();

//添加键值对 
dic.Add(0, "何润东");//参数1是键 ,参数2是值
dic.Add(1, "周传雄-情歌教父");

//根据键取值
Console.WriteLine(dic[0]);
Console.WriteLine(dic.Keys);//获取所有的键

//一般直接使用dic.Keys 和  dic.Values 不用再去定义一个变量去接收
// Dictionary<int,string>.KeyCollection keys =  dic.Keys;
// Dictionary<int,string>.ValueCollection values =  dic.Values;

dic.Remove(0); //指定键移除键值对
Console.WriteLine(dic.Count);//键值对的个数

Console.WriteLine(dic.ContainsKey(0)); //判断是否包含某个键
                                       // dic.Clear(); //清空键值对

//遍历所有键
foreach (var item in dic.Keys)
{
    Console.WriteLine(item + "----"); //每一个key
    //Console.WriteLine(dic[item]); // 根据key获取值
}


//遍历字典所有的值
foreach (var item in dic.Values) //  dic.Values 获取所有的值
{
    Console.WriteLine(item + "++++");
}

//遍历整个字典
foreach (var item in dic)
{
    Console.WriteLine(item.Key + ":" + item.Value);
}

//使用for循环遍历所有的值 dic.values 不能使用dic.Values[i]这种方式进行访问,需要转成数组之后再能使用[]方式访问
//但是字典dic[key]访问值
//for (int i = 0; i < dic.Values.Count; i++)
//{
//    Console.WriteLine(dic.Values.ToArray()[i]+"sss");
//}


//定义一个字典 键是班级的名字 值是一个班学员姓名数组
Dictionary<string, string[]> dic1 = new Dictionary<string, string[]>()
{
    {"一班", new string[]{ "马化腾","马云","马斯克"} },//键值对
    {"二班", new string[]{ "焦恩俊","严屹宽","霍建华","乔振宇"} }
};

string[] arr = dic1["一班"];
Console.WriteLine(string.Join("-", arr));

7.hashTable 哈希表

static void Main(string[] args)
{
    //C# 中的Hashtable是.NET 早期非泛型键值对哈希集合,基于哈希算法实现快速查找,存在装箱拆箱、类型不安全问题,现已被泛型Dictionary替代。
    //. 核心原理:放入数据给一个 Key 和 Value,通过哈希函数把 Key 转换成一个数字(哈希码) ,根据这个数字直接定位存储位
    Hashtable hashtable = new Hashtable()
    {
        {1,"这是1" },
        {true,"这是true" }
    };

    //1.Add()添加键值对
    hashtable.Add(0, "这是0");
    hashtable.Add(2, new int[] {1,2,3});

    //2.哈希表键值对个数
    Console.WriteLine(hashtable.Count);

    //3.取值
    Console.WriteLine(hashtable[1]);

    //4.修改
    hashtable[1] = 100;
    Console.WriteLine(hashtable[1]);

    //5.所有的keys的
    Console.WriteLine(hashtable.Keys);

    //6.所有的values
    Console.WriteLine(hashtable.Values);

    //7.遍历所有值
    foreach (var item in hashtable.Values)
    {
        Console.WriteLine(item+"---");
    }

    //8.移除键值对
    hashtable.Remove(0);
    //hashtable.Clear();

    //9.包含
    Console.WriteLine(hashtable.ContainsKey(0));
}

8.sortList有序列表

static void Main(string[] args)
{
    //sortList:通过键进行排序的列表,存储的是键值对
    SortedList list = new SortedList()
    {
        {13,"秦琼" },
        {10,"罗成" },
        {3,"裴元庆" },
        {2,"宇文成都" },
        {1,"李元霸" },
        //{"a","ss" }"a"与数字无法比较
    };

    //添加键值对
    list.Add(4, "熊阔海");

    //修改键值对
    list[10] = "杨林";

    //按照键删除
    list.Remove(4);
    //按照索引删除
    list.RemoveAt(3);

    //list.Clear(); 全部删除
    //Console.WriteLine(list.Keys);
    //Console.WriteLine(list.Values);


    //GetByIndex(0) 通过索引值取值
    //如果索引值为0,值是键最小的键值对
    Console.WriteLine(list.GetByIndex(0)); 
    Console.WriteLine(list.GetByIndex(1));

    //GetKey 获取键 按照索引值
    //写成0 键是1
    Console.WriteLine(list.GetKey(0));


    //GetValueList 获取所有值
    for (int i = 0; i < list.GetValueList().Count; i++)
    {
        Console.WriteLine(list.GetValueList()[i]+"-----");
    }


    //遍历
    foreach (var item in list.Values)
    {
        Console.WriteLine(item+"+++");
    }
}

9.栈和队列

static void Main(string[] args)
{
    //栈:存储数据的容器,特点先入后出的,添加一个元素叫入栈,删除一个元素叫出栈
    Stack<int> stack = new Stack<int>();//泛型的定义方式
    Stack stack1 = new Stack();//非泛型的定义方式
    stack1.Push("张三");//入栈 栈底
    stack1.Push("李四");
    stack1.Push("王五");

    Console.WriteLine(stack1.Pop());//Pop() 删除并返回栈顶对象,王五

    Console.WriteLine(stack1.Peek());//Peek() 返回栈顶对象,李四

    for (int i = 0; i < stack1.Count; i++)
    {
        Console.WriteLine(stack1.ToArray()[i]);
    }

    foreach (var item in stack1)
    {
        Console.WriteLine(item+"---");
    }
    //stack.Clear();
    //stack.Contains(0);

    //队列的特点:先入先出的特点 添加一个元素叫入队,删除一个元素叫出队

    Queue<string> queue = new Queue<string>();
    queue.Enqueue("hello1");//入队
    queue.Enqueue("hello2");
    queue.Enqueue("hello3");

    Console.WriteLine(queue.Dequeue());//移除一个对象 并返回第一个开始的对象 hello1
    Console.WriteLine(queue.Peek());//hello2
    foreach (var item in queue)
    {
        Console.WriteLine(item);
    }
}

### Queue 类中的方法

下表列出了 Queue 类的一些常用的方法:

方法名 描述
public virtual void Clear() 从队列中移除所有的元素
public virtual bool Contains(object obj) 判断某个元素是否在队列中
public virtual object Dequeue() 移除并返回在队列开头的对象
public virtual void Enqueue(object obj) 向队列的末尾处添加一个对象
public virtual object[] ToArray() 复制队列到一个新的数组中
public virtual void TrimToSize() 将队列的容量设置为队列中元素的实际个数

更多推荐