目录
个人简单理解
冒泡:找到当前索引最小值(最大值),然后依次往后找最n小只(最n大值)
插入:与前面的有序数组比较
- 选择:与当前数,后面的数比较
- 快排:5个变量(四个边界,一个基准值用于比较。从右基准找到比基准值小的数,就放到左边;从左基准找到比基准值大的数,就放到右边),类似于二分查找,逐渐缩小范围(除基准值以外的左右两个范围)
冒泡排序
两个for循环,找到当前索引应该存放的值,如果两个数值不相同就进行交换。比如一个数组中最小值是0,那么索引0存放的值就是数值0
public static void BubbleSort(int[] nums)
{
for (int i = 0; i < nums.Length; i++)
{
for (int j = i+1; j < nums.Length; j++)
{
if (nums[i] > nums[j])
{
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
}
}
插入排序
- 升序:将当前数字取出来,和前面的有序数字进行比较,如果比前面的数字小就进行交换
- 我使用for+while循环,通过while循环可以避免冗余(如果在有序数组中,已经比前面一个数字大了,就不用继续进行比较了)
static void Main(string[] args)
{
//测试数据
int[] array = { 1, 4, 2, 43, 5, 61, 89, 34, 67, 32, 40 };
//将数据排序
InsertSort(array);
//排序后的数据
foreach (int arr in array)
{
Console.WriteLine(arr);
}
}
public static void InsertSort(int[] nums)
{
for (int i = 1; i < nums.Length; i++)
{
int temp = nums[i];
int j = i - 1;
//索引 >= 0,当前数小于前面的数
while (j >= 0 && temp < nums[j])
{
nums[j + 1] = nums[j];
j--;//方便下一次比较
}
//数值交换完,将最前面空着的数填充
nums[j + 1] = temp;
}
}
选择排序
- 先将索引0赋值为minIndex(最小数),然后与当前位置后的数逐一比较,如果比minIndex索引小,那么就交换索引
- 比较完后,判断当前索引是否等于minIndex索引,如果不相等,两个数就交换值(位置)
static void Main(string[] args)
{
//测试数据
int[] array = { 1, 4, 2, 5 };
//将数据排序
QuickSort(array);
//排序后的数据
foreach (int arr in array)
{
Console.WriteLine(arr);
}
}
public static void QuickSort(int[] arr)
{
for (int i = 0; i < arr.Length; i++)
{
int minIndex = i;//最小数索引
for (int j = i+1; j < arr.Length; j++)
{
//找到最小数,进行交换索引
if (arr[minIndex] > arr[j])
{
minIndex = j;
}
}
//i索引不是最小数,进行交换索引
if (minIndex != i)
{
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
}
快速排序
简单理解
理论
- 选取基准,产生左右标识,左右比基准,满足则换位
- 排完一次,基准定位
- 左右递归,直到有序
我自己的简单理解
- 确定左右标识、左右基准、基准值(一开始值为左基准值,也就是下图的3)
- 当前值为基准值,然后与左右基准值进行比较,通过换位确定基准值应该存在的位置
交换位置:基准值为3,从右基准的位置开始找比3小的数放到左边;然后再从左基准开始找比3大的数放到右边。
- 缩小范围继续比较(除基准值以外,确定两个区间范围)
static void Main(string[] args)
{
//测试数据
int[] array = { 1, 4, 2, 5 };
//将数据排序
QuickSort(array,0,array.Length - 1);
//排序后的数据
foreach (int arr in array)
{
Console.WriteLine(arr);
}
}
public static void QuickSort(int[] arr, int left, int right)
{
if (left >= right) return;
int tempLeft, tempRight, temp;
tempLeft = left;
tempRight = right;
temp = arr[left];
while (tempLeft != tempRight)
{
while (tempLeft < tempRight && arr[tempRight] < temp)
{
tempRight--;//移动右标识
}
arr[tempLeft] = arr[tempRight];//处理小于基准值的数,移动到左边
while (tempLeft < tempRight && arr[tempLeft] > temp)
{
tempLeft++;//移动左标识
}
arr[tempRight] = arr[tempLeft];//处理大于基准值的数,移动到右边
}
arr[tempLeft] = temp;//基准值通过排序,确定它应该放的位置
//缩小范围处理,除基准值之外的范围
QuickSort(arr, left, tempLeft - 1);
QuickSort(arr, tempRight + 1, right);
}
二分查找
原理:
- 折半查找,满足单调性,确定左右区间(左闭右开),不断的查找目标值
private static int BinarySearch(int[] array,int target)
{
int left = 0, right = array.Length - 1;
while (left<right)
{
int mid = (left + right) / 2;
if (array[mid] < target)
{
left = mid+1;
}
else
{
right = mid ;
}
}
if (array[left] == target)
{
return left;
}
else
{
return -1;
}
}
归并排序
原理:
- 基础排序
- 递归分解数组
图解:把一个数组一直拆分,最后数组长度小于2,就停止拆分
代码:基础排序
using System;
namespace 归并
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("程序内部会先分割数组,在对数组进行排序");
Console.WriteLine("自己在写归并的时候,可以先写排序函数,再写分割数组函数");
int[] arr = new int[] { 8, 7, 1, 5, 4, 2, 6, 3, 9 };//申明一个数组,待会进行排序
//需要申明一个新的数组用来接收排序完的数组,原数组虽然进行了排序,但只改变了原数组的地址(并非原数组的值)
//数组是引用类型,原数组的值在输出的时候不会受到改变
int[] arr2 = Merge(arr);
//打印输出数组排序
for (int i = 0; i < arr2.Length; i++)
{
Console.WriteLine(arr2[i]);
}
}
//基础排序函数 函数中的static不是必要的,是因为这个C#控制台程序的原因,不然写起来不方便
public static int[] Sort(int[] left,int[] right)
{
//新数组,用于存储排序后的数据
int[] array = new int[left.Length + right.Length];
//左数组的索引
int leftIndex = 0;
//右数组的索引
int rightIndex = 0;
for (int i = 0; i < array.Length; i++)
{
//如果left数组的数据都排序完了,就直接将right数组的数据放入新数组
if (leftIndex>=left.Length)
{
array[i] = right[rightIndex];
//索引加加,如果right数组有2,1;left数组有7,3。1先存到array数组,在继续循环
//会将right数组中的2和left数组中的数据进行判断
rightIndex++;
}
//如果right数组的数据都排序完了,就直接将left数组的数据放入新数组
//这个else if很重要,这四个判断语句只会执行其中的一条。如果都是if而不是elseif,那么就会去判断所有的if
else if (rightIndex >= right.Length)
{
array[i] = left[leftIndex];
leftIndex++;
}
//如果left数组的数据比右数组的数据要小,那么将left数组的数据放入新数组
else if (left[leftIndex] < right[rightIndex])
{
array[i] = left[leftIndex];
leftIndex++;
}
else
{
//如果right数组的数据比右数组的数据要小,那么将right数组的数据放入新数组
array[i] = right[rightIndex];
rightIndex++;
}
}
//将排序好的数组返回出去
return array;
}
//递归分割数组
public static int[] Merge(int[] array)
{
//结束递归的条件,不然递归会无限循环
//当数组长度小于2时,就不在分割
if (array.Length < 2)
return array;
//分割数组
int mid = array.Length / 2;
//分割后的左数组
int[] left = new int[mid];
//分割后的右数组
int[] right = new int[array.Length - mid];
for (int i = 0; i < array.Length; i++)
{
//left数组进行赋值
if (i < mid)
left[i] = array[i];
//right数组进行赋值 假如array数组一共有9个数,right数组长度为5。i为5时right就会进行赋值
//5 - 4(4是mid的值),对right数组中的第一个值进行赋值
else
right[i - mid] = array[i];
}
//利用递归,分割数组
//数组假如有9个数,一直除以2。当数组长度小于2时,才会进行排序
return Sort(Merge(left), Merge(right));
}
}
}