/// <summary> /// 选择排序 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="dataSources"></param> /// <param name="startIndex"></param> /// <param name="endIndex"></param> /// <param name="handle"></param> public static void Sort <T>(List <T> dataSources, SortCompareHandle <T> handle) { if (SortHelper.CheckParameter <T>(dataSources, handle) == false) { return; } int selectIndex = 0; for (int dex = 0; dex < dataSources.Count - 1; ++dex) //注意这里dex<endIndex-1 因为 下面一个循环中会取下一个元素 { selectIndex = dex; for (int j = dex + 1; j < dataSources.Count; ++j) { if (handle(dataSources[selectIndex], dataSources[j])) { selectIndex = j; //Debug.Log("Sort selectIndex=" + selectIndex); } } if (dex != selectIndex) { // Debug.LogInfor("dex=" + dex + " selectIndex=" + selectIndex); SortHelper.Swap <T>(dataSources, dex, selectIndex); } } }
/// <summary> /// 从第一个非叶子节点一直到根节点 比较根节点与左右两个子节点 如果满足条件就交换 然后调整交换后的子堆 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="dataSources"></param> /// <param name="i">当前比较的局部子树节点索引</param> /// <param name="size"></param> /// <param name="lessHandle"></param> private static void AdjustHeap <T>(List <T> dataSources, int i, int size, SortCompareHandle <T> lessHandle) { int lChild = 2 * i + 1; //左孩子 int rChild = 2 * i + 2; //右孩子 int maxIndex = i; //临时变量 记录最大的节点的索引值 if (i < size / 2) { //如果i是叶子节点就结束 if (lChild < size && lessHandle(dataSources[maxIndex], dataSources[lChild])) //dataSources[max] < dataSources[lChild]) { maxIndex = lChild; } if (rChild < size && lessHandle(dataSources[maxIndex], dataSources[rChild])) //dataSources[max] < dataSources[rChild]) { maxIndex = rChild; } if (maxIndex != i) { SortHelper.Swap <T>(dataSources, maxIndex, i); //交换后破环了子树的堆结构 AdjustHeap(dataSources, maxIndex, size, lessHandle); //递归,调节子树为堆 } } }
//建立堆,堆是从下往上建立的,因为adjustHeap函数是建立在子树已经为大顶堆。 private static void BuildHeap <T>(List <T> dataSource, int size, SortCompareHandle <T> lessHandle) { for (int i = size / 2; i >= 0; i--) {//从最后一个非叶子节点,才能构成adjustHeap操作的目标二叉树 AdjustHeap(dataSource, i, size, lessHandle); } }
/// <summary> /// 检测参数是否合法 或者是否需要排序 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="dataSources"></param> /// <param name="startIndex"></param> /// <param name="endIndex"></param> /// <param name="handle"></param> /// <returns></returns> public static bool CheckParameter <T>(List <T> dataSources, SortCompareHandle <T> handle) { if (dataSources == null || dataSources.Count <= 1 || handle == null) { return(false); } return(true); }
/// <summary> /// 归并排序 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="dataSources"></param> /// <param name="first"></param> /// <param name="last"></param> /// <param name="Handle"></param> /// <param name="temp">用于排序时候的临时分配数据 这里创建避免每次创建 (注意 temp必须是已经初始化的list 否则会报错)</param> public static void Sort <T>(List <T> dataSources, int first, int last, SortCompareHandle <T> Handle, List <T> temp) { if (first < last) { int mid = (first + last) / 2; // Debug.Log("first=" + first + " last" + last + " mid=" + mid); Sort(dataSources, first, mid, Handle, temp); //左边有序 Sort(dataSources, mid + 1, last, Handle, temp); //右边有序 mergearray <T>(dataSources, first, mid, last, Handle, temp); //再将二个有序数列合并 } }
/// <summary> /// 插入排序 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="dataSources"></param> /// <param name="handle"></param> public static void Sort <T>(List <T> dataSources, SortCompareHandle <T> handle) { if (SortHelper.CheckParameter <T>(dataSources, handle) == false) { return; } for (int i = 1; i < dataSources.Count; i++) { for (int j = i - 1; j >= 0 && handle(dataSources[j], dataSources[j + 1]); j--) { SortHelper.Swap <T>(dataSources, j, j + 1); } } }
//将数组分为两部分,一部分为有序区,在数组末尾,另一部分为无序区。堆属于无序区 /// <summary> /// 堆排序 排序后的结果是一个从小到大的结果 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="dataSources"></param> /// <param name="lessHandle">比较两个数据小于的比较方法</param> public static void Sort <T>(List <T> dataSources, SortCompareHandle <T> lessHandle) { BuildHeap(dataSources, dataSources.Count, lessHandle); //首先建立基本的堆结构 //for (int dex = 0; dex < dataSources.Count; ++dex) //{ // Debug.Log(dataSources[dex]); //} for (int i = dataSources.Count - 1; i > 0; i--) { //i为无序区的长度,经过如下两步,长度递减 //堆顶即下标为0的元素 SortHelper.Swap <T>(dataSources, i, 0); //1.每次将堆顶元素和无序区最后一个元素交换,即将无序区最大的元素放入有序区 AdjustHeap(dataSources, 0, i, lessHandle); //2.将无顺区调整为大顶堆,即选择出最大的元素。 } }
/// <summary> /// 简单的冒泡排序 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="dataSources"></param> /// <param name="startIndex"></param> /// <param name="endIndex"></param> /// <param name="handle"></param> public static void Sort <T>(List <T> dataSources, SortCompareHandle <T> handle) { if (SortHelper.CheckParameter <T>(dataSources, handle) == false) { return; } int count = 0; //已经完成的排序次数 for (int dex = 0; dex < dataSources.Count; ++dex) { for (int j = 0; j < dataSources.Count - count - 1; ++j) { if (handle(dataSources[j], dataSources[j + 1])) { SortHelper.Swap <T>(dataSources, j, j + 1); } } ++count; } }
public static void Sort <T>(List <T> dataSources, SortCompareHandle <T> handle) { if (SortHelper.CheckParameter <T>(dataSources, handle) == false) { return; } int[] sedgewick = Sedgewick(dataSources.Count);// 得到塞奇威克(Sedgewick) 步长序列数组 for (int dex = 0; dex < sedgewick.Length; ++dex) { Debug.Log(sedgewick[dex]); } int s, k, i, j; T t; // 循环出所有步长 for (s = sedgewick.Length - 1; s >= 0; s--) { // 步长为sedgewick[s] 即分为 sedgewick[s] 个组 for (k = 0; k < sedgewick[s]; k++) { // 对每组数据进行排序 for (i = k + sedgewick[s]; i < dataSources.Count; i += sedgewick[s]) { // 分组中,按插入排序排序数据,交换数据按步长 sedgewick[s] t = dataSources[i]; j = i - sedgewick[s]; while (j >= 0 && handle(dataSources[j], t)) //dataSources[j] > t) { dataSources[j + sedgewick[s]] = dataSources[j]; j -= sedgewick[s]; } dataSources[j + sedgewick[s]] = t; } } } }
/// <summary> /// 将有二个有序数列a[first...mid]和a[mid...last]合并。 /// 思路:依次取出两个List的第一个元素比较大小,取出最大或者最小一个元素保存到临时列表中。当有一个list数据取完时候另一个List数据直接全部加在临时数据后面即可 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="dataSources"></param> /// <param name="first"></param> /// <param name="mid"></param> /// <param name="last"></param> /// <param name="handle"></param> /// <param name="temp"></param> private static void mergearray <T>(List <T> dataSources, int first, int mid, int last, SortCompareHandle <T> handle, List <T> temp) { int i = first; int j = mid + 1; int m = mid; int n = last; int k = 0; //记录一共有多少数据被保存到临时List中 while (i <= m && j <= n) { if (handle(dataSources[i], dataSources[j])) { temp[k++] = dataSources[i++]; } else { temp[k++] = dataSources[j++]; } }//当两个List中数据都没有取完时候 while (i <= m) { temp[k++] = dataSources[i++]; } while (j <= n) { temp[k++] = dataSources[j++]; } for (i = 0; i < k; i++) { dataSources[first + i] = temp[i]; } }
/// <summary> /// 数据分组 返回值时下一次排序时候中间轴的位置索引 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="dataSources"></param> /// <param name="startIndex"></param> /// <param name="endIndex"></param> /// <param name="ratherEqualHandle"></param> /// <param name="lessEqualHandle"></param> /// <returns></returns> private static int Partition <T>(List <T> dataSources, int startIndex, int endIndex, SortCompareHandle <T> ratherEqualHandle, SortCompareHandle <T> lessEqualHandle) { int pivotIndex = startIndex; T pivot = dataSources[startIndex]; //枢轴记录 int leftPoint = 0; //记录左侧比轴数据小的数据索引 int rightPoint = 0; //记录右 侧比轴数据大的数据索引 //****思路: 先从当前子数组的末尾开始找到第一个小于轴数据并记录索引值,然后从左往右找到第一个比轴数据大的元素索引,然后交换两个记录索引对应的数据,继续查找 ,直到左右两个索引相同时候与轴数据交换 while (startIndex < endIndex) { while (startIndex < endIndex && ratherEqualHandle(dataSources[endIndex], pivot)) // dataSources[endIndex] >= pivot) { --endIndex; } rightPoint = endIndex; //小于轴数据并记录索引值 while (startIndex < endIndex && lessEqualHandle(dataSources[startIndex], pivot)) //dataSources[startIndex] <= pivot) { ++startIndex; } leftPoint = startIndex; //大于轴数据并记录索引值 SortHelper.Swap <T>(dataSources, leftPoint, rightPoint); //交换两个记录数据 } SortHelper.Swap <T>(dataSources, pivotIndex, startIndex); //当前这次已经找到轴的位置 //返回的是枢轴的位置 return(startIndex); }
/// <summary> /// 简单的快速排序 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="dataSources">需要排序的数据源</param> /// <param name="startIndex">排序的起始索引</param> /// <param name="endIndex">排序的结束索引</param> /// <param name="ratherEqualHandle">泛型化判断是否是大于等于 </param> /// <param name="lessEqualHandle">泛型化判断是否是小于等于 </param> public static void Sort <T>(List <T> dataSources, int startIndex, int endIndex, SortCompareHandle <T> ratherEqualHandle, SortCompareHandle <T> lessEqualHandle) { if (startIndex < endIndex) { int pivot = Partition <T>(dataSources, startIndex, endIndex, ratherEqualHandle, lessEqualHandle); //将数组分为两部分 Sort <T>(dataSources, startIndex, pivot - 1, ratherEqualHandle, lessEqualHandle); //递归排序左子数组 Sort <T>(dataSources, pivot + 1, endIndex, ratherEqualHandle, lessEqualHandle); //递归排序右子数组 } }