using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Algorithm : MonoBehaviour
{
//排序算法
public int[] arr = { 0, 5, 7, 6, 9, 4, 3, 2, 8, 1 };
private void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
BubbleSort();
} if (Input.GetKeyDown(KeyCode.S))
{
SelectionSort();
} if (Input.GetKeyDown(KeyCode.D))
{
InsertionSortFor();
} if (Input.GetKeyDown(KeyCode.F))
{
InsertionSortWhile();
} if (Input.GetKeyDown(KeyCode.G))
{
InsertSortBinary(arr);
} if (Input.GetKeyDown(KeyCode.H))
{
ShellSortHibbard(arr);
}
}
/// <summary>
/// 三种交换方式
/// </summary>
#region 三种交换方式
// 方法一: 利用临时数tmp
private void swap(int[] arr, int i, int j)
{
/*int tmp = arr[i];
arr[i] = arr[j+1];
arr[j+1] = tmp;*/
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
// 方法二: 利用加减运算
private void swapCal(int[] arr, int i, int j)
{
if (i == j) return; // 若无法保证swapCal被调用时满足 i != j,则需有此句,否则i == j时此数将变为0
arr[i] = arr[i] + arr[j]; // a = a + b
arr[j] = arr[i] - arr[j]; // b = a - b
arr[i] = arr[i] - arr[j]; // a = a - b
}
// 方法三: 利用异或运算
private void swapXOR(int[] arr, int i, int j)
{
if (i == j) return; // 若无法保证swapXOR被调用时满足 i != j,则需有此句,否则i == j时此数将变为0
arr[i] = arr[i] ^ arr[j]; // a = a ^ b,也可写成 arr[i] ^= arr[j];
arr[j] = arr[i] ^ arr[j]; // b = (a ^ b) ^ b = a ^ (b ^ b) = a ^ 0 = a, 也可写成 arr[j] ^= arr[i];
arr[i] = arr[i] ^ arr[j]; // a = (a ^ b) ^ a = (a ^ a) ^ b = 0 ^ b = b, 也可写成 arr[i] ^= arr[j];
}
#endregion
/// <summary>
/// 算法
/// </summary>
#region 冒泡排序
public void BubbleSort()
{
for (int i = 0; i < arr.Length - 1; i++)
{
for (int j = 0; j < arr.Length - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
/*int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;*/
swap(arr, i, j);
}
}
}
}
#endregion
#region 选择排序
public void SelectionSort()
{
for (int i = 0; i < arr.Length; i++)
{
int minIndex = i;
int min = arr[i];
for (int j = i + 1; j < arr.Length; j++)
{
if (arr[j] < min)
{
min = arr[j];
minIndex = j;
}
}
arr[minIndex] = arr[i];
arr[i] = min;
}
}
#endregion
#region 插入排序
//简单插入排序 内层用 for
public void InsertionSortFor()
{
if (arr.Length < 2)
{
return;
}
for (int i = 1; i < arr.Length; i++)
{
int target = arr[i], j;
for (j = i - 1; j >= 0; j--)
{
if (target < arr[j])
arr[j + 1] = arr[j];
else break;
}
arr[j + 1] = target;
}
}
//简单插入排序 内层用 while
public void InsertionSortWhile()
{
if (arr.Length < 2)
{
return;
}
for (int i = 1; i < arr.Length; i++)
{ // N-1轮次执行
int target = arr[i], j = i - 1;
while (j >= 0 && target < arr[j])
{
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = target; // 若发生移动,此时的插入对象数字≥j位置的数字,故插入位置为j + 1,若未移动也成立,无需判断
}
}
//折半插入排序
private int BinarySearch(int[] arr, int l, int r, int target)
{
while (l <= r)
{
int c = l + (r - l) / 2;
if (arr[c] <= target) l = c + 1;
else r = c - 1;
}
return l;
}
public int[] InsertSortBinary(int[] arr)
{
if (arr.Length < 2) return arr;
// n - 1 轮次执行
for (int i = 1; i < arr.Length; i++)
{
// 通过二分查找得到插入位置
int target = arr[i];
int pos = BinarySearch(arr, 0, i - 1, target);
for (int j = i; j > pos; j--)
{ // 移动
arr[j] = arr[j - 1];
}
arr[pos] = target; // 插入
}
return arr;
}
#endregion
#region 希尔排序 (增量递减排序)
//Shell增量 采用Shell增量 N / 2^k
public int[] ShellSortShell(int[] arr)
{
if (arr.Length < 2) return arr;
int n = arr.Length;
for (int gap = n / 2; gap > 0; gap /= 2)
{ // gap 初始为 n/2,缩小gap直到1
for (int start = 0; start < gap; start++)
{ // 步长增量是gap,当前增量下需要对gap组序列进行简单插入排序
for (int i = start + gap; i < n; i += gap)
{ // 此for及下一个for对当前增量序列执行简单插入排序
int target = arr[i], j = i - gap;
for (; j >= 0; j -= gap)
{
if (target < arr[j]) arr[j + gap] = arr[j];
else break;
}
arr[j + gap] = target;
}
}
}
return arr;
}
//Hibbard增量
// 希尔排序: 采用Hibbard增量 {1, 3, 7, 15,...}
public int[] ShellSortHibbard(int[] arr)
{
if (arr.Length < 2) return arr;
int n = arr.Length, gap = 1;
while (gap < n / 2) gap = gap * 2 + 1; // 初始化gap (Hibbard增量序列)
for (; gap > 0; gap /= 2)
{ // 缩小gap直到1
for (int start = 0; start < gap; start++)
{ // 步长增量是gap,当前增量下需要对gap组序列进行简单插入排序
for (int i = start + gap; i < arr.Length; i += gap)
{ // 此for及下一个for对当前增量序列执行简单插入排序
int target = arr[i], j = i - gap;
for (; j >= 0; j -= gap)
{
if (target < arr[j]) arr[j + gap] = arr[j];
else break;
}
arr[j + gap] = target;
}
}
}
return arr;
}
//Knuth 增量
public int[] ShellSortKnuth(int[] arr)
{
if (arr.Length < 2) return arr;
int n = arr.Length, gap = 1;
while (gap < n / 3) gap = gap * 3 + 1;//初始化gap(Knuth增量序列)
for (; gap > 0; gap /= 3)
{
//缩小gap到1
for (int start = 0; start < gap; start++)
{
//步长增量是gap,当前增量下需要对gap组序列进行简单插入排序
for (int i = start + gap; i < arr.Length; i += gap)
{
//此for及下一个for对当前增量序列执行简单插入排序
int target = arr[i], j = i - gap;
for (; j >= 0; j -= gap)
{
if (target < arr[j]) arr[j + gap] = arr[j];
else break;
}
arr[j + gap] = target;
}
}
}
return arr;
}
//Sedgewick增量
/*public int[] shellSortSedgewick(int[] arr)
{
if (arr.Length < 2) return arr;
int n = arr.Length, gap = 1;
List<Integer> gaps = new ArrayList<>();
gaps.add(gap);
for (int k = 1; gap < n; k++)
{ // 计算增量序列
gap = (int)(Math.pow(4, k) + 3 * Math.pow(2, k - 1) + 1);
gaps.add(gap);
}
for (int idx = gaps.size() - 1; idx >= 0; --idx)
{ // 缩小 gap 直到 1
gap = gaps.get(idx);
for (int start = 0; start < gap; start++)
{ // 步长增量是 gap ,当前增量下需要对 gap 组序列进行简单插入排序
for (int i = start + gap; i < n; i += gap)
{ // 此 for 及下一个 for 对当前增量序列执行简单插入排序
int target = arr[i], j = i - gap;
for (; j >= 0; j -= gap)
{
if (target < arr[j]) arr[j + gap] = arr[j];
else break;
}
arr[j + gap] = target;
}
}
}
return arr;
}*/
#endregion
#region 归并排序
#region 自顶向下 非原地归并
public int[] Mergesort(int[] arr)
{
if (arr.Length < 2) return arr;
int[] tmpArr = new int[arr.Length];
Mergesort1(arr, tmpArr, 0, arr.Length - 1);
return arr;
}
//递归方法
private void Mergesort1(int[] arr, int[] tmpArr,int l,int r)
{
if (l < r)
{
int c = l + (r - 1) / 2;
Mergesort1(arr, tmpArr, l, c);
Mergesort1(arr, tmpArr, c + 1, r);
Merge(arr, tmpArr, l, c, r);
}
}
//非原地合并方法
private void Merge(int[] arr, int[] tmpArr, int l, int c, int r)
{
// lh: left head, rh: right head, h: tmpArr head
int lh = l, rh = c + 1, h = l;
while (lh <= c && rh <= r)
{
tmpArr[h++] = arr[lh] <= arr[rh] ? arr[lh++] : arr[rh++];
}
while (lh <= c) tmpArr[h++] = arr[lh++]; // 左半边还有剩余,加入 tmpArr 末尾
while (rh <= r) tmpArr[h++] = arr[rh++]; // 右半边还有剩余,加入 tmpArr 末尾
for (; l <= r; l++) arr[l] = tmpArr[l]; // 将 tmpArr 拷回 arr 中
}
#endregion 自顶向下 原地归并
#region
#endregion
#endregion
#region 快速排序
#endregion
}
C#排序算法
最新推荐文章于 2024-11-03 16:33:21 发布