//
// Created by TYP on 2023/9/2.
//

#include "CAlgorithm.h"

void CAlgorithm::SortDirectSelectMethod(int array[], int nSize)
{
    if (nSize < 2)
        return;

    int index = -1;
    int nTemp = -1;
    for (int i = 0; i < nSize - 1; ++i) {
        // 进行 n-1 趟选择
        index = i + 1;
        // 从无序区选取最小的记录
        for (int j = index; j < nSize; ++j) {
            if (array[index] > array[j])
                index = j;
        }

        nTemp = array[i];
        array[i] = array[index];
        array[index] = nTemp;

        // printf("Step %d:\n", i);
        // PrintArrayInt(array, nCnt);
    }
}

void CAlgorithm::SortQuickMethod(int array[], int nStartIndex, int nEndIndex)
{ /*NOLINT*/
    // 基准值和一个临时变量
    int nBasic = array[nStartIndex];
    int nTemp = -1;

    // 保存起始位置
    int nStart = nStartIndex;
    int nEnd = nEndIndex;

    while (nStart < nEnd) {
        // 从右向左搜索小于基准值的数, 比基准值大的(不包含相等)则向左边挪动
        while (nStart < nEnd && nBasic < array[nEnd])
            --nEnd;
        // 从左向右搜索大于基准值的数, 比基准值小的(不包含相等)则向右边挪动
        while (nStart < nEnd && nBasic > array[nStart])
            ++nStart;
        // start 在 end 的右侧则查询无效。
        if (nStart >= nEnd)
            continue;
        // 交换数据
        nTemp = array[nEnd];
        array[nEnd] = array[nStart];
        array[nStart] = nTemp;

        // printf("分块前 while 循环内:");
        // PrintArrayInt(array, 8);
    }

    // 跳出循环之后,把更换基准值
    nTemp = nBasic;
    nBasic = array[nStart];
    array[nStart] = nTemp;

    // start 和 end
    // 碰头之后就把数据分成了左右两块,分别对左右两个块作相同的处理。
    if (nStartIndex < nEnd)
        SortQuickMethod(array, nStartIndex, nEnd - 1);
    if (nStart < nEndIndex)
        SortQuickMethod(array, nEnd + 1, nEndIndex);
}

void CAlgorithm::SortBubbleMethord(int array[], int nSize)
{
    if (nSize < 2)
        return;

    int nTemp = -1;

    // 不需要和自己比较,比较次数 -1
    for (int i = 0; i < nSize - 1; ++i) {
        int count = 0;
        for (int j = 0; j < nSize - 1 - i; ++j) {
            // 升序
            if (array[j] > array[j + 1]) {
                nTemp = array[j];
                array[j] = array[j + 1];
                array[j + 1] = nTemp;
                count = 1;
            }
        }
        // 如果某一趟没有交换位置,则说明已经排好序,直接退出循环
        if (count == 0)
            break;
    }
}

void SortDirectSelectMethodTest()
{
    int data[] = {34, 546, 12, 67, 77, 126, 980, 346};
    int nSize = sizeof(data) / sizeof(int);
    printf("Sort Before:");
    PrintArrayInt(data, nSize);
    printf("data's size:%d\n", nSize);

    CAlgorithm::SortDirectSelectMethod(data, nSize);

    printf("Sort After:");
    PrintArrayInt(data, nSize);
}

void SortQuickMethodTest()
{
    int data[] = {34, 546, 12, 67, 77, 126, 980, 346};
    int nSize = sizeof(data) / sizeof(int);
    printf("Sort Before:");
    PrintArrayInt(data, nSize);
    printf("data's size:%d\n", nSize);

    CAlgorithm::SortQuickMethod(data, 0, 7);

    printf("Sort After:");
    PrintArrayInt(data, nSize);
}

void SortBubbleMethordTest()
{
    int data[] = {34, 546, 12, 67, 77, 126, 980, 346};
    int nSize = sizeof(data) / sizeof(int);
    printf("Sort Before:");
    PrintArrayInt(data, nSize);
    printf("data's size:%d\n", nSize);

    CAlgorithm::SortBubbleMethord(data, 8);

    printf("Sort After:");
    PrintArrayInt(data, nSize);
}