async和await的底层原理
c#中,async和await本身是语法糖。编译器遇见async函数时,会去函数内找await,并将await前后分割为多个代码片段,将代码片段放在一个状态机中。
每当有空闲线程分配时,就会调用状态机MoveNext()方法去执行下一个代码片段。
深拷贝需要注意什么问题
需要对成员变量中的引用类型字段,进行深拷贝,直接赋值只会引用到相同对象。
public T DeepCopy<T>(T obj)
{
object ret;
using (var ms = new MemoryStream())
{
XmlSerializer serializer = new XmlSerializer(typeof(T));
serializer.Serialize(ms, obj);
ms.Seek(0, SeekOrigin.Begin);
ret = serializer.Deserialize(ms)!;
}
return (T)ret;
}
快速排序
时间复杂度O(nlogn)。核心原理是分治法,以数组第一个值为中间值,小于中间值的都放在数组左边,大于的都放在右边。然后分别对中间值的左边部分和右边部分数组,进行递归式的快速排序。
public class QuickSortExample
{
public static void Main()
{
int[] array = { 10, 3, 5, 7, 2, 8, 6, 4, 9, 1 };
QuickSort(array, 0, array.Length - 1);
Console.WriteLine("Sorted array: ");
foreach (int value in array)
{
Console.Write(value + " ");
}
}
private static void QuickSort(int[] arr, int left, int right)
{
if (left < right)
{
// 获取分区后的枢纽位置
int pivotIndex = Split(arr, left, right);
// 分别对枢纽左右两边的子数组进行递归排序
QuickSort(arr, left, pivotIndex - 1);
QuickSort(arr, pivotIndex + 1, right);
}
}
private static int Split(int[] arr, int left, int right)
{
// 选择数组的最右侧作为枢纽值
int pivot = arr[right];
int i = left;
for (int j = left; j <= right - 1; j++)
{
if (arr[j] <= pivot)
{
Swap(ref arr[i], ref arr[j]);
i++;
}
}
// 将枢纽值放到正确的位置
Swap(ref arr[i], ref arr[right]);
// 返回枢纽位置
return i;
}
private static void Swap(ref int a, ref int b)
{
int temp = a;
a = b;
b = temp;
}
}