1:个人学习记录。
2:大佬请绕道。。。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace DataStructure.wcc
{
//TODO:数据结构与算法
class DataStructureAlgorithm
{
int[] listTest = new int[] { 90, 10, 30, 20, 50, 40, 60, 80, 70, 0 };
#region 稳定排序:归并排序、冒泡排序、插入排序。
#region 冒泡排序:是相邻元素之间的比较和交换,两重循环O(n2);所以,如果两个相邻元素相等,是不会交换的。所以它是一种稳定的排序方法
///
/// 冒泡排序
///
public void PopSort()
{
int temp = 0;
for (int i = 0; i < listTest.Length-1; i++)
{
for (int J = i+1; J < listTest.Length; J++)
{
//从小到大排序:当找到比当前小的数时交换位置再继续向后查找看还没有比当前数小的
if(listTest[i]>listTest[J])
{
temp = listTest[i];
listTest[i] = listTest[J];
listTest[J] = temp;
}
}
}
for (int i = 0; i < listTest.Length; i++)
{
Debug.Log(listTest[i] + "!!!!!");
}
}
#endregion
#region 插入排序:每步将一个待排序的纪录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。
///
/// 插入排序
///
public void Insertion()
{
//从小到大排列
for (int i = 1; i < listTest.Length; i++)
{
int k = listTest[i];
int keepI = i;
for (int m = i-1; m >=0 ; m--)
{
//遍历I位置前面的值有没有小于K的有的话就交换位置
if(k < listTest[m])
{
int temp = listTest[m];
listTest[m] = listTest[keepI];
listTest[keepI] = temp;
keepI--;
}
}
}
for (int i = 0; i < listTest.Length; i++)
{
Debug.Log(listTest[i] + "!!!!!");
}
}
#endregion
#region 归并排序
//百度百科定义:归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
//下面用通俗易懂的语言来描述该算法,归并排序算法是一个自下而上的排序算法,先使子序列有序,然后合并两个相邻子序列,并使得到的序列仍然有序,这样逐级向上归并,最终达到使整个序列有序的目的。
//同时归并排序算法还有一个任务,即分割序列,因为我们得到的无序序列是一个整体,我们需要将它分割开,以供归并操作使用。
//下面讲解算法实现部分:
//一:向Merge_sort函数传递要排序的序列array;
//二:Merge_sort函数使用二分法将array分割成两个子序列array[0:mid + 1] 和array[mid + 1:length], 并同时对两个子序列使用Merge_sort函数进行递归。由此引申出对Merge_sort函数参数的讨论,首先它需要array,其次需要所要排序部分的区间,即left和right。
//三:此时已经实现了将序列自上而下进行了分割,还未对序列进行自下而上的归并。所以应该在分割完成之后进行归并,且是每一次分割完成之后都需要使用Merge函数归并。即可得到下述代码:
public static void Merge_sortStart()
{
int[] listTest = new int[] { 90, 10, 30, 20, 50, 40, 60, 80, 70, 0 };
int[] temps = new int[listTest.Length];
Merge_sort(listTest, 0, listTest.Length - 1, temps);
foreach (int item in listTest)
{
Debug.Log(item + "归并排序///");
}
}
static void Merge_sort(int[] array, int left, int right, int[] temp)
{
if (left < right)
{
int mid = (int)((left + right) / 2);
Merge_sort(array, left, mid, temp);
Merge_sort(array, mid + 1, right, temp);
int l1 = left;
int r1 = mid;//第一个有序序列
int l2 = mid + 1;
int r2 = right;//第二个有序序列
//这两个序列本身就是相邻的
int k = 0;
//下面代码是将 两个有序序列合并,并使合并后的序列仍然有序
while (l1 <= r1 && l2 <= r2)
{
if (array[l1] <= array[l2])
{
temp[k++] = array[l1++];
}
else
{
temp[k++] = array[l2++];
}
}
while (l1 <= r1)
{
temp[k++] = array[l1++];
}
while (l2 <= r2)
{
temp[k++] = array[l2++];
}
for (int i = 0; i < k; i++)
{
array[left + i] = temp[i];
}
}
}
#endregion
#endregion
#region 不稳定排序:选择排序、快速排序、堆排序
#region 快排
/*该方法的基本思想是
1.先从数列中取出一个数作为基准数。
2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
3.再对左右区间重复第二步,直到各区间只有一个数。
*/
///
/// 快排
///
///
public void FastRow()
{
FastRowList(listTest, 0, listTest.Length - 1);
for (int i = 0; i < listTest.Length; i++)
{
Debug.Log(listTest[i] + "!!!!!");
}
}
void FastRowList(int[] vs, int Left, int Right)
{
if (Right > Left)
{
//基准数
int x = vs[Left];
//数组开始索引
int i = Left;
//数组最后一位索引
int j = Right;
while ( i < j)//当i等于j的时候跳出循环
{
//从后往前找小于当前基准数的位置
while ( i < j)
{
//后向前找到小于当前基准数 进行复制
if (vs[j] <= x)
{
vs[i] = vs[j];
break;
}
else
{
//下一个位置
j--;
}
}
//从前往后找大于当前基准数的位置 现在坑的位置在j
while ( i < j)
{
//从前往后找大于基准数 进行复制 现在坑的位置在j
if (vs[i] > x)
{
vs[j] = vs[i];
break;
}
else
{
//下一个位置
i++;
}
}
}
//现在i等于j了 把X储存的值 给到i的位置
vs[i] = x;
//当前区间分成了left>I>Right
//再次递归调用当前方法
FastRowList(vs, Left, i - 1);
FastRowList(vs, i + 1, Right);
}
}
#endregion
#region 选择排序:从待排序的记录序列中选择关键码最小(或最大)的记录并将它与序列中的第一个记录交换位置以此类推;
public void SelectSort()
{
for (int i = 0; i < listTest.Length-1; i++)
{
int least = listTest[i];
int K= i;
for (int m = i+1; m < listTest.Length; m++)
{
//记录最小值以及位置
if(listTest[m] < least)
{
least = listTest[m];
K= m;
}
}
//判断下当前索引是最小值时
if(K!= i)
{
listTest[K] = listTest[i];
listTest[i] = least;
}
}
foreach (int item in listTest)
{
Debug.Log(item + " 选择排序");
}
}
#endregion
#region 堆排序
//堆分为大根堆和小根堆,是完全二叉树。大根堆的要求是每个节点的值都不大于其父节点的值,即A[PARENT[i]] >= A[i]。
//在数组的升序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定在堆顶。
public static void TestHeapSort()
{
int[] listTest = new int[] { 90, 10, 30, 20, 50, 40, 60, 80, 70, 0 };
HeapSort(listTest);
foreach (var item in listTest)
{
Debug.Log(item + "堆排序//");
}
}
private static void HeapSort(int[] array)
{
MaxHeap(array);
for (int i = array.Length - 1; i > 0; i--)
{
Swap(ref array[0], ref array[i]);
Heapify(array, 0, i);
}
}
private static void MaxHeap(int[] array)
{
for (int i = array.Length / 2 - 1; i >= 0; i--)
{
Heapify(array, i, array.Length);
}
}
private static void Heapify(int[] array, int index, int size)
{
int left = 2 * index + 1;
int right = 2 * index + 2;
int large = index;
if (left < size && array[left] > array[large])
{
large = left;
}
if (right < size && array[right] > array[large])
{
large = right;
}
if (index != large)
{
Swap(ref array[index], ref array[large]);
Heapify(array, large, size);
}
}
///
/// 交换
///
///
///
private static void Swap(ref int first, ref int second)
{
int t = first;
first = second;
second = t;
}
#endregion
#endregion
}
}