/// <summary>
/// 快速排序,如果你的key值取得是左边的第一个数,则先从右边开始挖坑,如果取得是右边的最后一个数,则从左边开始挖坑
/// </summary>
/// <param name="s"></param>
/// <param name="l"></param>
/// <param name="r"></param>
void quick_sort(int [] s, int l, int r)
{
if (l < r)
{
//Swap(s[l], s[(l + r) / 2]); //将中间的这个数和第一个数交换 参见注1
int low = l, High = r, x = s[r];
while (low < High)
{
while (low < High && s[low] <= x) // 从左向右找第一个大于等于x的数
low++;
if (low < High)
s[High--] = s[low];
while (low < High && s[High] >= x) // 从右向左找第一个小于x的数
High--;
if (low < High)
s[low++] = s[High];
}
s[low] = x;
quick_sort(s, l, low - 1); // 递归调用
quick_sort(s, low + 1, r);
}
}
int PartSort1(int[] arr, int left, int right)
{
int end = right;
int begin = left;
int key = arr[left];
while (begin < end)
{
while (begin < end && arr[begin] <= key)
begin++;
while (begin < end && arr[end] >= key)
end--;
if (begin < end)
Swap(arr [begin], arr[end]);
}
Swap(arr[begin], arr[right]);
return begin;
}
/// <summary>
/// 插入排序的思想就是,从右至左,比较一个数和它左边所有的数,如果遇到大于或者小于这个数的,就把他左边的数往左移或者往右移,最后把该数插入到结尾的位置,实现交换
/// </summary>
/// <param name="arry"></param>
/// <param name="sortIndex"></param>
public void InsertSort(int[] arry, int sortIndex)
{
if (arry.Length > 1)
{
int j = 0;
for (int i = 1; i < sortIndex; i++)//从第二个数开始
{
int temp = arry[i];
for (j = i - 1; j >= 0; j--)//依次比较这个数和它左边的数
{
if (temp >= arry[j])//如果遇到比这个数小地数,则把这个数往后移一位,依次查询,直到最后一个或者是一个不小于这个数的数,因为插入排序要插入的数的左边都是已经排列好了的
{ //大于等于是从大到小排列,小于等于是从小往大排列
arry[j + 1] = arry[j];//从这个小于的数开始,依次往后移
}
else
break;
}
arry[j + 1] = temp;//把要插入的值插入到移动完空缺的那个位置上
}
}
foreach (var item in arry)
{
print(item);
}
}
/// <summary>
/// 二分法排序,不是二分法查找,思想是先跟据要排列的数的索引找到一个中间值,把这个值和中间值比较,直到找到低位大于高位的时候,把从低位开始或者高位开始的值,依次往左或者往右移动,最后把要排列的数插入到空缺的位置
/// </summary>
/// <param name="arry">插入排序是依次和它左边的值作比较,这个是依次和左边的中间值作比较,所以查找的次数要小于插入排序</param>
/// <param name="size"></param>
public void BinarySort(int[] arry, int size)
{
for (int i = 1; i < size; i++)
{
int low = 0;
int high = i - 1;
int mid;
int j;
int temp = arry[i];
while (low <= high)//一直找到low>high的时候,这样
{
mid = (low + high) / 2;
if (temp > arry[mid])//
{
high = mid - 1;
}
else
{
low = mid + 1;
}
}
for (j = i - 1; j > high; j--)//这里大于high或者大于等于low都是一样的,因为他俩是相邻的
{
arry[j + 1] = arry[j];
}
arry[j + 1] = temp;
}
foreach (var item in arry)
{
print(item);
}
}
/// <summary>
/// 二分法查找,必须是有序数组,而且
/// </summary>
/// <param name="arry"></param>
/// <param name="find"></param>
/// <returns></returns>
public int BinaryFind(int[] arry, int find)
{
int low = 0;
int high = arry.Length;
int mid = (low + high) / 2;
while (low < high)
{
mid = (low + high) / 2;
if (find > arry[mid])
{
low = mid + 1;
}
else if (find < arry[mid])
{
high = mid - 1;
}
else
{
return mid;
}
}
return -1;
}
/// <summary>
/// 乱序算法,思想:从数组里面随机取出一个数,和数组中的第一个数字交换位置,然后再从除了第一个数字之外随机取一个位置,和第二个数交换位置
/// </summary>
/// <param name="arry"></param>
public void Disorder(int[] arry)
{
for (int i = 0; i < arry.Length; i++)
{
int temp = Random.Range(i, arry.Length);
int tempIndex = arry[i];
arry[i] = arry[temp];
arry[temp] = tempIndex;
}
foreach (var item in arry)
{
Debug.Log(item);
}
}
/// <summary>
/// 从数组里面找到一个最小的,和第一位交换位置,然后再从第二个数开始找到一个最小的,放在第二个位置,这个和洗牌算法差不多,只不过是洗牌是随机从里面找一个数,和第一位交换位置
/// </summary>
/// <param name="arry"></param>
public void SecletSort(int[] arry)
{
for (int i = 0; i < arry.Length; i++)
{
int min = i;
for (int j = i + 1; j < arry.Length; j++)
{
if (arry[j] < arry[min])
{
min = j;
}
}
Swap(arry[i], arry[min]);
}
DebugItem(arry);
}
public void DebugItem(int[] arry)
{
foreach (var item in arry)
{
Debug.Log(item);
}
}
/// <summary>
/// 交换两个数
/// </summary>
/// <param name="source"></param>
/// <param name="des"></param>
public void Swap(int source, int des)
{
source = source ^ des;
des = source ^ des;
source = source ^ des;//交换两个值,用异或的方法
}
求数组中第k大的值
利用快排算法,第一次排序,得到一个以key值为中间点,左右两边为小于和大于它的数,然后比较这个key值的索引和K的大小,因为第一次比较之后,key值所在的位置就是第key所在索引大的位置,因为数组是从0开始的,第五大也就是索引为index+1,比如key的索引为3,那它是第3+1=4大的值,如果k>index+1,说明,在key值的右边,则重新对右边进行一次快速排序,得到一个key值所在的索引,继续比较,如果k<index+1,说明K在key值得左边,则重新在左边进行快速排序,直到得到key和index+1相等,返回当前index得值
static int RandPartition(int[] arr, int left, int right) {
2 Random rd = new Random();
3 int p = rd.Next(left, right + 1);//随机得到一个key值,增强基值得选择性,避免单一key值,在已经排好序得情况下得浪费比较时间
4 Swap(ref arr[p], ref arr[left]);//转换成左边值,虽然key值是随机的,但有转换成了和不随机得处理方法
5 int temp = arr[left];
6 while (left < right) {
7 while (left < right && arr[right] > temp) { right--; count++; }
8 arr[left] = arr[right];
9 while (left < right && arr[left] <= temp) { left++; count++; }
10 arr[right] = arr[left];
11 }
12 arr[left] = temp;
13 return left;
14 }
15
16 static int RandSelect(int[] arr, int left, int right, int k) {
17 if (left == right) {
18 return arr[left];//如果到最后数组就剩一个数了,说明这个是就是
19 }
20 int index = RandPartition(arr, left, right);
21 int M = index + 1;
22 if (M == k) {
23 return arr[index];
24 }
25 int result = -1;
26 if (M < k) {
27 result = RandSelect(arr, index + 1, right, k);
28 }
29 else if (M > k) {
30 result = RandSelect(arr, left, index - 1, k);
31 }
32 return result;
33 }