private IEnumerator IEnumRandomQuickSort(T[] sort_item, QuickSortParameter <T> sort_parameter, int left, int right) { int[] pivot_index = new int[1]; { int rand_index = Mathf.FloorToInt(UnityEngine.Random.Range(left, right - float.Epsilon)); if (left != rand_index) { swap_temp = sort_item[left]; sort_item[left] = sort_item[rand_index]; sort_item[rand_index] = swap_temp; dirty_items[left] = dirty_items[rand_index] |= SortItemState.Exchanged | SortItemState.Comparison; sort_parameter.cb_action(SortState.Exchange, sort_item, dirty_items); dirty_items[left] = dirty_items[rand_index] &= ~(SortItemState.Exchanged | SortItemState.Comparison); } else { dirty_items[rand_index] |= SortItemState.Comparison; sort_parameter.cb_action(SortState.Compare, sort_item, dirty_items); dirty_items[rand_index] &= ~SortItemState.Comparison; } } //先頭に対して、大小を分ける。. dirty_items[left] |= SortItemState.Pivot; yield return(IEnumQuickSortBase(sort_item, sort_parameter, left + 1, right, left, pivot_index)); dirty_items[left] &= ~SortItemState.Pivot; int back_ite = pivot_index[0] - 1; if (pivot_index[0] <= left) { } else { {//先頭と境界を入れ替える swap_temp = sort_item[left]; sort_item[left] = sort_item[pivot_index[0]]; sort_item[pivot_index[0]] = swap_temp; dirty_items[left] = dirty_items[pivot_index[0]] |= SortItemState.Exchanged | SortItemState.Comparison; sort_parameter.cb_action(SortState.Exchange, sort_item, dirty_items); dirty_items[left] = dirty_items[pivot_index[0]] &= ~(SortItemState.Exchanged | SortItemState.Comparison); yield return(waiter); } } dirty_items[pivot_index[0]] = SortItemState.SortEnd; if (pivot_index[0] > left) { for (int k = right - 1; k > pivot_index[0]; --k) { dirty_items[k] |= SortItemState.DisableArea; } yield return(IEnumRandomQuickSort(sort_item, sort_parameter, left, pivot_index[0])); for (int k = right - 1; k > pivot_index[0]; --k) { dirty_items[k] &= ~SortItemState.DisableArea; } } //この時点で左は完成してる if (pivot_index[0] + 1 < right) { yield return(IEnumRandomQuickSort(sort_item, sort_parameter, pivot_index[0] + 1, right)); } }
/// <summary> /// クイックソートのベース関数 /// </summary> /// <param name="sort_item">[in,out]ソートアイテム</param> /// <param name="comparer">[in]比較演算</param> /// <param name="left">[in]ソートする左端(含む)</param> /// <param name="right">[in]ソートする右端(含まず)</param> /// <param name="pivot">[in]比較対象値</param> /// <param name="next_pivot_index">[out]比較対象との境界位置(左側列の再右端要素)</param> /// <returns></returns> private IEnumerator IEnumQuickSortBase(T[] sort_item, QuickSortParameter <T> sort_parameter, int left, int right, int pivot, int[] next_pivot_index) { int back_ite = right; int dst_pivot = back_ite; int front_ite = left - 1; while (true) {//両端から、入れ替えの必要な二つを探して交換する if (front_ite >= left) { dirty_items[front_ite] |= SortItemState.Comparison; } while (true) { if (front_ite + 1 < back_ite) { --back_ite; dirty_items[back_ite] |= SortItemState.Comparison; sort_parameter.cb_action(SortState.Compare, sort_item, dirty_items); dirty_items[back_ite] &= ~SortItemState.Comparison; if (sort_parameter.comparer.Compare(sort_item[pivot], sort_item[back_ite]) > 0) { break; } } else { next_pivot_index[0] = back_ite - 1; if (front_ite >= left) { dirty_items[front_ite] &= ~SortItemState.Comparison; } yield break; } } if (front_ite >= left) { dirty_items[front_ite] &= ~SortItemState.Comparison; } dirty_items[back_ite] |= SortItemState.Comparison; while (true) { if (front_ite + 1 < back_ite) { ++front_ite; dirty_items[front_ite] |= SortItemState.Comparison; sort_parameter.cb_action(SortState.Compare, sort_item, dirty_items); dirty_items[front_ite] &= ~SortItemState.Comparison; if (sort_parameter.comparer.Compare(sort_item[pivot], sort_item[front_ite]) < 0) { break; } } else { next_pivot_index[0] = back_ite; dirty_items[back_ite] &= ~SortItemState.Comparison; yield break; } } dirty_items[back_ite] &= ~SortItemState.Comparison; swap_temp = sort_item[front_ite]; sort_item[front_ite] = sort_item[back_ite]; sort_item[back_ite] = swap_temp; dirty_items[front_ite] = dirty_items[back_ite] |= SortItemState.Exchanged | SortItemState.Comparison; sort_parameter.cb_action(SortState.Exchange, sort_item, dirty_items); dirty_items[front_ite] = dirty_items[back_ite] &= ~(SortItemState.Exchanged | SortItemState.Comparison); yield return(waiter); } }