C#學習筆記(十八):數據結構和泛型
阿新 • • 發佈:2019-02-11
eric 訪問 空間 cap 添加數據 mes 出錯 雙向 添加
鏈表(數據量大,萬計以上)
若幹個小塊構成,每個小塊由三個單元格構成,若幹個單元格相互關聯(當前元素的後一元素指向下一個元素的當前元素)
雙向鏈表:前一元素、當前元素、後一元素
單向鏈表:當前元素、後一元素
1、動態增長
2、C#鏈表沒有下標
3、索引元素特別慢,一個個查找,可以用叠代器優化
4、元素不是相連的,修改元素特別快
泛型集合和集合功能相似,增加了泛型的特性
集合:需要轉成Object,存在性能消耗,轉換會出錯
泛型集合:通過翻譯官轉化,效能無損
List列表
Capcity默認長度、Count實際元素個數、Data(Int[])數組
添加元素超過默認長度,會調用Data重新創建一個Capcity * 2的新數組,舊數組變為垃圾
添加準確的初始長度,或給出一個合理基數,可以減少性能消耗
數據結構
只有這四種 a、集合:數據之間沒有特定的關系 b、線性結構:數據之間有一對一的前後聯系 c、樹形結構:數據之間有一對多的關系,一個父節點有多個子節點,一個子節點只能有一個父節點 d、圖狀結構:數據之間有多對多的關系,一個節點可以有多個子節點,也可以多個父節點 線性結構:列表、鏈表、棧、隊列 樹形結構:字典 列表(數據量小,100以下,無腦使用) 1、列表可以動態增長,數組不可以動態增長 2、列表可以不通過下標添加元素,數組不可以 3、列表索引元素特別快(首地址加下標),但是內存中的元素必須相連,不允許跳過單元格 4、列表修改元素效能差,當刪除(插入)元素時,需要把後面的元素一個個的向前(向後)移散列結構:數據取余,哈希表,哈希算法MD5(把無限的數據存儲在有限的空間中) 碰撞:兩個數據取余相同,盡量避免數據相同(索引:必須唯一,值:可以相同)
1、允許任意類型(不考慮具體類型,只考慮變化關系) 2、但必須是同一類型
泛型:統一代碼邏輯應用於所有類型
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace m1w4d4_list { //在我們要使用泛型集合時 //首先我們要確認是否using System.Collections.Generic; class Monster { } class Program { //我們學習了列表的數據結構(增刪改查) //實例化,屬性 //增加元素 //刪除元素 //訪問,修改元素 //插入元素 //查找元素 static void Main(string[] args) { #region 泛型列表 //泛型列表允許我們做任意類型的列表,只需要在<>中填入相應類型 List<int> list = new List<int>();//這種構造讓我使用默認的初始長度(4) List<int> list1 = new List<int>(10);//這種構造允許我們設置列表的初始長度 List<Monster> list3 = new List<Monster>(); //list.Capacity; Capacity表示列表的實際長度 //list.Count; Count表示list中有多少個有意義的元素 //添加元素 list.Add(123); //訪問元素 //通過索引器可以訪問對應元素,但索引器的標號必須小於Count Console.WriteLine(list[0]); Console.WriteLine(list.Capacity);//初始為0.由Add創建 Console.WriteLine(); //修改元素 for (int i = 0; i < 10; i++) { list.Add(i); } for (int i = 0; i < list.Count; i++) { Console.Write(list[i] + " "); } Console.WriteLine("\t"); list[4] = 999; for (int i = 0; i < list.Count; i++) { Console.Write(list[i] + " "); } Console.WriteLine("\n"); //刪除元素 list.RemoveAt(0);//移除指定下標中的元素 for (int i = 0; i < list.Count; i++) { Console.Write(list[i] + " "); } Console.WriteLine(); list.Remove(999);//移除指定元素(從頭查找到的) for (int i = 0; i < list.Count; i++) { Console.Write(list[i] + " "); } Console.WriteLine("\n"); //插入元素 //list.Insert();//在指定下標處,插入指定元素,原元素及其後的元素均排在插入元素的後方 list.Insert(4, 999); for (int i = 0; i < list.Count; i++) { Console.Write(list[i] + " "); } Console.WriteLine("\n"); //查找元素 //從頭查找 int id = list.IndexOf(999);//根據元素從頭查找,並返回找到的第一個元素的位置 Console.WriteLine($"從頭查找,刪除值為{list[id]}的元素"); list.RemoveAt(id);//刪除從頭找到的第一個元素 for (int i = 0; i < list.Count; i++) { Console.Write(list[i] + " "); } Console.WriteLine("\n"); //從尾查找 int id1 = list.LastIndexOf(8);//根據元素從尾查找,並返回找到的第一個元素的位置 Console.WriteLine($"從頭查找,刪除值為{list[id1]}的元素"); list.RemoveAt(id);//刪除從尾找到的第一個元素 for (int i = 0; i < list.Count; i++) { Console.Write(list[i] + " "); } Console.WriteLine("\n"); #endregion //遍歷 //用for,遍歷次數是Count //for (int i = 0; i < list.Count; i++) //{ // Console.Write(list[i] + " "); //} //用foreach //foreach (var item in list) //{ //} #region 練習1 //建立一個整型List,給List中添加倒序添加10-1 Console.WriteLine("建立一個整型List,給List中添加倒序添加10-1"); for (int i = 10; i >= 1; i--) { list1.Add(i); } //刪除List中的第五個元素 list1.RemoveAt(4); //遍歷剩余元素並打印出來 foreach (var item in list1) { Console.Write(item + " "); } Console.WriteLine(); #endregion } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace m1w4d4_list1 { #region 泛型列表排序IComparable public class Monster : IComparable<Monster> { public Monster(string name, int attack, int defend, int health) { this.name = name; this.attack = attack; this.defend = defend; this.health = health; } public string name; public int attack; public int defend; public int health; public override string ToString() { return string.Format("{0},攻擊{1},防禦{2},血量{3}", name, attack, defend, health); } public static int DefendSort(Monster a, Monster b) { return a.defend - b.defend; } public int CompareTo(Monster other) { //比較某一個參數,返回對應值 //如果大就返回大於0的數,自己排在對比參數的後面 //如果小就返回小於0的數,自己排在對比參數的前面 //如果相等就返回0,不換 //這樣在外部調用Sort的時候會形成一個以這個參數為標準的升序排序 return attack - other.attack; } } #endregion #region 泛型列表排序IComparer class MonsterAttackSort : IComparer<Monster> { //這個方法是用 參數x 和參數y 比較,返回相應整數 //如果返回大於零的數,x將放在y的後面,如果用升序的邏輯,就是x比y大 //如果返回大於零的數,x將放在y的後面 //如果返回零,表示相等 public int Compare(Monster x, Monster y) { return x.attack - y.attack; } } class MonsterDefendSort : IComparer<Monster> { public int Compare(Monster x, Monster y) { return x.defend - y.defend; } } class MonsterHealthSort : IComparer<Monster> { public int Compare(Monster x, Monster y) { return x.health - y.health; } } #endregion class Program { #region 泛型列表排序Comparition static int AttackSort(Monster a, Monster b) { return a.attack - b.attack; } #endregion //用一個List排序 //泛型集合都是實現System.Collections.Generic;中對應接口的一些類型 //如果要實現一個自定義類的排序 //1、實現一個IComparable的接口 //2、調用Sort的重載,用一個接口類型IComparer //3、調用Sort的重載,用一個委托類型Comparition //需要一個和List裝載的類型相同的一排序方法 int 函數名 (對應類型 對應類型) static void Main(string[] args) { #region 泛型列表排序 Random roll = new Random(); List<int> list = new List<int>(); for (int i = 10 - 1; i >= 0; i--) { list.Add(roll.Next(0, 100)); } foreach (var item in list) { Console.Write(item + " "); } Console.WriteLine("\n"); list.Sort();//通過Sort對List進行(升序)排序 foreach (var item in list) { Console.Write(item + " "); } Console.WriteLine("\n"); list.Reverse();//通過Sort對List進行(升序)排序 foreach (var item in list) { Console.Write(item + " "); } Console.WriteLine("\n"); #endregion #region 排100000個數 //用冒泡排序,排100000個數,速度沒有Sort快 List<int> list1 = new List<int>(); for (int i = 0; i < 100000; i++) { list1.Add(roll.Next(0, 100)); } int temp = list1[0]; for (int i = 0; i < 100000 - 1; i++) { for (int j = 0; j < 100000 - 1 - i; j++) { if (list1[i] > list1[i + 1]) { temp = list1[i]; list1[i] = list1[i + 1]; list1[i + 1] = temp; } } } foreach (var item in list1) { Console.Write(item + " "); } Console.WriteLine("\n"); //用Sort排序,排100000個數 List<int> list2 = new List<int>(); for (int i = 0; i < 100000 - 1; i++) { list2.Add(roll.Next(0, 100)); } list2.Sort(); foreach (var item in list2) { Console.Write(item + " "); } Console.WriteLine("\n"); #endregion #region 泛型列表排序IComparable List<Monster> monsterList = new List<Monster>(); for (int i = 0; i < 10; i++) { monsterList.Add(new Monster("怪物" + (i + 1) + "號", roll.Next(10, 20), roll.Next(10, 20), roll.Next(10, 20))); } monsterList.Sort(); foreach (var item in monsterList) { Console.WriteLine(item); } Console.WriteLine("\n"); #endregion #region 泛型列表排序IComparer //排序器 MonsterAttackSort mAttackSort = new MonsterAttackSort(); MonsterDefendSort mDefendSort = new MonsterDefendSort(); MonsterHealthSort mHealthSort = new MonsterHealthSort(); monsterList.Sort(mAttackSort); monsterList.Sort(mDefendSort); monsterList.Sort(mHealthSort); //monsterList.Reverse(); foreach (var item in monsterList) { Console.WriteLine(item); } Console.WriteLine("\n"); #endregion #region 泛型列表排序Comparition monsterList.Sort(AttackSort); foreach (var item in monsterList) { Console.WriteLine(item); } Console.WriteLine("\n"); monsterList.Sort((a,b)=>-(a.health - b.health)); foreach (var item in monsterList) { Console.WriteLine(item); } Console.WriteLine("\n"); monsterList.Sort(Monster.DefendSort); foreach (var item in monsterList) { Console.WriteLine(item); } Console.WriteLine("\n"); #endregion } } }
復習
委托補充
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 委托補充 { // 創建一個數據類型 delegate void Del1(); delegate void Del2(int n); delegate void Del3(string n); delegate void Del4(int a, string b, char c, bool d); delegate int Del5(); delegate string Del6(int n); delegate int Del7(int a, string b, bool c); class Program { static void Main(string[] args) { #region 沒有返回值的委托 Action // Aciton 針對於沒有返回值的委托 // 沒有參數的 那就不用泛型的 直接用Aciton // 有參數的 那就根據參數的個數和類型來使用泛型的Aciton<T1 a, T2 b, T3 c ....> // 使用 Del1 del1 = delegate () { Console.WriteLine("這是一個沒有參數,沒有返回值的委托"); }; Action del1 = delegate () { Console.WriteLine("這是一個沒有參數,沒有返回值的委托"); }; del1(); //Del2 del2 = n => Console.WriteLine("這是一個沒有返回值,有一個參數的委托"); Action<int> del2 = n => Console.WriteLine("這是一個沒有返回值,有一個參數的委托" + n); del2(100); Action<string> del3 = n => Console.WriteLine("這是一個沒有返回值,有一個字符串的參數的委托" + n); del3("abc"); Action<int, string, char, bool> del4 = (int a, string b, char c, bool d) => { }; #endregion #region 有返回值的委托 Func<T1, T2, T3....> 最後一個占位符 永遠對應返回值類型 (占位符最少有1個,最多可以有20多個,來表示返回值類型的) Func<int> del5 = () => 0; Func<int, string> del6 = abc => abc.ToString(); Func<int, string, bool, int> del7 = (a, b, c) => a; #endregion #region Predicate有一個參數,參數的類型由泛型占位符指定 返回值 bool Predicate<string> del9 = a => true; #endregion #region Comparison<int> 有兩個參數都是根據泛型占位符指定的類型 返回值int Comparison<string> del8 = (a, b) => a.Length - b.Length; #endregion } } }
泛型列表
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 泛型列表 { class Program { static void Main(string[] args) { // List 動態數組 List<int> array = new List<int>(); List<int> array2 = new List<int>() { 303, 27, 309, 40 }; // 使用初始化器添加數據 // 增 array.Add(1000); array.AddRange(new int[] { 1, 2, 3, 42 });//AddRange批量增加,數組和列表 array.AddRange(array2); // 刪 //array.Remove(1000); // 刪到找到的第一個 沒找到也不發生什麽 //array.RemoveAt(0); //array.RemoveRange(0, 3); // 刪除一定範圍的元素 從哪個下標開始, 總共刪除幾個元素 //array.RemoveAll(n => n % 2 == 0); // 把所有偶數全部刪除 // 改 //array[0] = 888; // 查 int index = array.IndexOf(301); // 找不到會返回 -1 Console.WriteLine("找到的下標為:" + index); index = array.LastIndexOf(301); Console.WriteLine("找到的下標為:" + index); int result = array.Find(n => n % 40 == 0); // 找到匹配條件的第一個元素,Find查找返回的是元素 Console.WriteLine(result); List<int> resultArray = array.FindAll(n => n % 3 == 0);//FindAll查找返回的是新的列表 foreach (var item in resultArray) { Console.Write(item + "\t"); } // 遍歷 //for (int i = 0; i < array.Count; i++) //{ // Console.Write(array[i] + "\t"); //} Console.WriteLine(); } } }
C#學習筆記(十八):數據結構和泛型