本文介绍了冒泡排序和选择排序的核心逻辑与实现,以及C#中Dictionary字典的使用方法。冒泡排序通过相邻元素比较交换将最大值"冒泡"到末尾,选择排序则通过选择最值元素与未排序区间首元素交换。Dictionary字典通过键值对存储数据,支持高效查找和修改操作。最后对比了var和dynamic类型的区别:var首次赋值确定类型后不可更改,而dynamic类型在运行时动态解析且可随时变更类型。文章还简要提及了强类型和弱类型编程语言的特点。
冒泡排序
核心逻辑:
重复遍历排序序列,相邻元素两两相比,如果前面的元素大于后面的元素这个时候交换位置。
每一轮遍历会将当前未排序部分的最大元素 “冒泡” 到末尾;
重复上述过程,直到所有元素有序(从小到大,或从大到小)
例子:
List<int> list = new List<int>() { 1, 99, 2, 7, 11, 5, 28, 14 }; // 外层循环:控制排序轮数 //原理:n个元素最多需要n-1轮排序(因为每轮确定1个最值的位置,最后1个元素无需再轮询) for (int i = 0; i < list.Count-1; i++) { for (int j=0;j<list.Count-1-i;j++) // 内层循环:每轮遍历未排序区间,相邻元素比较+交换 { if (list[j] > (list[j+1]))// 比较相邻位置交换位置 如果前面的大则交换位置 { int temp = list[j];// 定义一个临时值 存储前一个元素的值 list[j] = list[j + 1];// 后一个元素前移,覆盖前一个元素 list[j + 1] = temp;// 临时变量的值赋给后一个元素,完成交换 } } }选择排序
核心逻辑:
将序列分为已排序区间和未排序区间,每一轮从未排序区间中找到最值(升序找最小值、降序找最大值),将其与未排序区间的第一个元素交换位置;重复此过程,直到未排序区间为空。
简单来说,选择排序的核心是 “先选最值,再交换”,而非冒泡排序的 “相邻交换、逐步冒泡”。
代码:
List list=new List() { 1,23,5,3,77,44,6,7,8,9}; for (int i=0;i<list.Count-1;i++) { int minIndex = i;//每一轮循环的 把i当成最小值的索引值 for (int j = i+1; j < list.Count; j++) { //取出最小值索引:list[minIndex],如果其中的一个元素比最小值还小,这时候list[j]最小值 if (list[minIndex] > list[j]) { minIndex = j; } } //在内循环外部进行交换位置 if (i!=minIndex)//如果找到的最小的和初始化的赋值的最小的不一样进行交换 { //list[minIndex] 和list[i]进行交换 object temp = list[i]; list[i] = list[minIndex];//最小值赋值给当前遍历的元素 已经排序的末尾 list[minIndex] = temp; } } //.join()把参数2的数组用参数1的符号进行拼接成一个字符串 Console.WriteLine(string.Join(", ",list));Dictionary字典
字典:包含了key(键)和value(值) 简称为键值对,键是唯一的,值可以是任意类型的,字典是没有顺序的,只能通过键取值
使用场景:当你有一组数据,每个数据都有唯一标识(键),且需要频繁通过这个标识查找对应数据时,优先用字典。
对比列表:列表查找元素需遍历所有元素,字典直接通过键定位,效率天差地别。
例子
1.字典键值对的初始化方式
//方法一 索引式([key] = value):底层是索引赋值,重复键覆盖值(无异常); Dictionary<int, string> dic1 = new Dictionary<int, string>() { [123124] = "王五",//参数1键唯一,参数2是值 }; //方法二 集合初始化器(集合式)([key] = value):底层是 Add,重复键抛异常; Dictionary<int, string> dic2 = new Dictionary<int, string>() { {321,"张三" },//参数1键唯一,参数2是值 {123,"李四" }, }; //方法三 向字典添加元素 Dictionary<string, string> dic3 = new Dictionary<string, string>(); dic3.Add("老六", "男");//参数1键唯一,参数2是值 dic3.Add("赵一", "男");2.取出值
Dictionary<int, string> dic = new Dictionary<int, string>() { [123124] = "王五",//参数1键唯一,参数2是值 }; Console.WriteLine(dic["news1"]); //根据键取出值 Console.WriteLine(dic.Values); //获取所有的值的集合 Console.WriteLine(string.Join("-",dic.Values)); foreach (var item in dic.Values) { Console.WriteLine(item); }3.取出键
Dictionary<int, string> dic = new Dictionary<int, string>() { [123124] = "王五",//参数1键唯一,参数2是值 }; Console.WriteLine(dic1.Keys);//获取所有键的集合 Array.ForEach(dic.Keys.ToArray(),v=> Console.WriteLine(v+"////")); //dic,Keys.ToArray()转成数组类型4.修改值
Dictionary<string, string> dic = new Dictionary<string, string>() { ["王五"] = "男", }; dic["王五"] = "女";5.根据键进行删除
Dictionary<string, string> dic = new Dictionary<string, string>() { ["王五"] = "男" }; dic.Remove("王五");6.清空集合
Dictionary<string, string> dic = new Dictionary<string, string>() { ["王五"] = "男" }; dic.Clear();7.是否包含news3键
Dictionary<string, string> dic = new Dictionary<string, string>() { ["王五"] = "男" }; Console.WriteLine(dic.ContainsKey("王五"));8. 取出字典所有的键值对,使用foreach循环先遍历键 再根据键获取值
Dictionary<string, string> dic = new Dictionary<string, string>() { ["王五"] = "男", ["张三"] = "男", ["李思"] = "女", }; foreach (var item in dic.Keys) { Console.WriteLine($"名字:{iten} ,性别:{dic[item]}); //根据键来获得对应的值 }var和dynamic的区别
var(隐式类型)
var 可以接收任意类型的数据,变量的实际类型由首次赋值的值的类型确定类型,且一旦确定,后续不能更改为其他类型。
用 var 替代具体类型关键字,无需手动指定变量类型。
示例:
var i = 10; //int 类型 var str = "张三";//string 类型 //后续对str赋其他类型的值,会报错 //str = 20; 报错dynamic(动态类型):无“首次赋值定类型” 的规则,真正支持接收任意类型数据 —— 变量类型不绑定到某一个值,仅在程序运行时根据当前赋值动态解析,且可随时变更类型(比如 dynamic a=10 之后,再赋值 a="hello" 完全合法,无编译错误)。
dynamic:类型完全可变,赋值无任何类型限制,同一变量可先后接收整数、字符串、布尔值等不同类型的值。
//dynamic 动态类型定义,也可以接收任意类型的数据 dynamic name = "world"; dynamic i= 10; i= "hello"; Console.WriteLine(name);强类型编程语言:定义一个数据 一旦确定数据的类型,这个数据不能在赋值成其他类型 好处:类型安全 ,坏处需要类型的转换
C#强类型语言
弱类型编程语言:定义一个数据 以后的代码可以修改数据的类型 坏处:类型不安全 。好处不需要类型的转换
js弱类型