排序算法

#include <iostream>
#define MAXSIZE 10
typedef struct  
{
    int r[MAXSIZE + 1];//用于存储排序的数组,r[0]用作哨兵或临时变量
    int length;           //用于记录顺序表的长度
}SqlList;

void swap(SqlList* L, int i, int j)
{
    int temp = L->r[i];
    L->r[i] = L->r[j];
    L->r[j] = temp;
}
/*
基本思想:从头开始将每个元素与后面的每个元素比较,将较小的放在当前位置,这样下来就将最小的元素放在了当前位置
但前面排好的对后面的没有作用,也许较小的放到后面了
*/
void BubbleSort0(SqlList* L)
{
    int i, j;
    for (i = 1; i < L->length; ++i)
    {
        for (j = i + 1; j <= L->length; ++j)
        {
            if (L->r[i] > L->r[j])
            {
                swap(L, i, j);    //交换i和j对应元素的值
            }
        }
    }
}

//从后往前比较
void BubbleSort(SqlList* L)
{
    int i, j;
    for (i = 1; i < L->length; ++i)
    {
        for (j = L->length - 1; j >= i; j--)
        {
            if (L->r[j] > L->r[j + 1])
            {
                swap(L, j, j + 1);
            }
        }
    }
}


//从前往后比较
void BubbleSort1(SqlList* L)
{
    int i, j;
    bool bFalg = true;//如果一次比较没变动直接退出循环,提高效率
    for (i = 1; i < L->length && bFalg; ++i)
    {
        bFalg = false;
        for (j = 1; j <= L->length - i; ++j)
        {
            if (L->r[j] > L->r[j + 1])
            {
                swap(L, j, j + 1);
                bFalg = true;
            }
        }
    }
}


/*
选择排序,从前往后记录最小位置,然后找出后面最小的然后和当前位置交换,这个是比较次数较多,外层for只进行一次比较
*/
void SelectSort(SqlList* L)                
{
    int i, j, min;
    for (i = 1; i < L->length; ++i)
    {
        min = i;
        for (j = i + 1; j <= L->length; ++j)
        {
            if (L->r[min] > L->r[j])
            {
                min = j;
            }
        }
    }
    if (i != min)
    {
        swap(L, i, min);
    }
}

/*
基本思想:先假定前面排好序,然后将要排序的插入到前面有序的数组中
o(n2)性能比冒泡和简单选择排序性能要好
*/
void InsertSort(SqlList* L)
{
    for (int i = 2; i < L->length; ++i)
    {
        L->r[0] = L->r[i];//当前元素存储在哨兵中
        int j;
        for (j = i - 1; j >= 1; --j)
        {
            if (L->r[j] > L->r[0])
            {
                L->r[j + 1] = L->r[j];
            }
            else
            {
                break;
            }
        }
        L->r[j + 1] = L->r[0];
    }
}

int Partition(SqlList* L, int low, int high)
{
    int val = L->r[low];// 存放要分割的值
    while (low < high && L->r[high] > L->r[low])//先进行high移动,只要比分割值大就左移
        high--;
    swap(L, low, high);//对应的值小于分割值,则进行替换l对应值
    while (low < high && L->r[low] < L->r[high])//进行low移动,比分割之小右移
        low++;
    swap(L, low, high);//如果大于分割值替换h对应值
    return low;
}

void QSort(SqlList* L, int low, int high)
{
    int pivot;
    if (low < high)
    {
        pivot = Partition(L, low ,high);
        //左右部分的排序
        QSort(L, low, pivot - 1);
        QSort(L, pivot + 1, high);
    }
}

/*
先选择轴值,左右指针,如果右边的索引比轴值小往做移动,然后比较左边,如果左边的索引比轴值大往右移动,当左索引和右索引相等时该位置就是轴值呆的地方
然后再比较轴值左边的,在比较轴值右边的
通过一趟将待排序的记录,将记录分割成两部分,一部分比另一部分小,接下来再进行左右两部分记录的排序
*/
void QuickSort(SqlList* L)
{
    QSort(L, 1, L->length);
}

/*
基本思想:每次按照跨度排序,然后这个跨度不断的减小,每次排序内部是插入排序
插入排序对于基本有序和较短的序列有较高的效率,时间复杂度为n1.5次方
并且这个跨度有限制的,例如除以二递减还是n2方的
*/
void ShellSort(SqlList* L)
{
    int i, j;
    int increment = L->length;
    do 
    {
        increment = increment / 3 + 1;//增量选择
        for (i = increment + 1; i <= L->length; i++)
        {
            if (L->r[i] < L->r[i - increment])//内部就是根绝增量的插入排序
            {
                L->r[0] = L->r[i];
                for (j = i - increment; j > 0 && L->r[0] < L->r[j]; j -= increment)
                {
                    L->r[j + increment] = L->r[j];
                }
                L->r[j + increment] = L->r[0];
            }
        }
    } 
    while (increment > 1);
}

void MSort(int SR[], int TR1[], int s, int t)
{
    int m;
    int TR2[MAXSIZE + 1];
    if (s == t)
    {
        TR1[s] = SR[s];
    }
    else
    {
        s = (s + t) / 2;
        MSort(SR, TR2, s, m);
        MSort(SR, TR2, m + 1, t);
        //Merge(TR2, TR1, s, m, t);未实现看大话
    }
}


/*
看这个归并排序很复杂,程序更是复杂,能写出来的也是牛B
                3 4 21 45 52 134 4 67 45 34
              3 4 21 45 52      134 4 67 45 34
            3 4 21  45 52      134 4 67  45 34
        3 4  21    45  52   134 4   67   45  34
        3 4 21    45 52    4 134      34 45 67
        3 4 21 45 52            4 34 45 67 134
          3 4 4 21 34 45 45 52 67 134
    其大体思想就是先进行对半分割,然后再两两合并排序一直到所有的都排序了
*/
void MergeSort(SqlList* L)
{
    MSort(L->r, L->r, 1, L->length);
}

/*
堆排序(理解思路就行了,写就算了)
先将待排序的数字建成最小值堆,建立最小值堆的速度还是挺快的
堆:分为大根堆和小根堆,属于完全二叉树(完全二叉树可以用数组存储)
加入要从小排序,就每次从根节点取,最从小排序了
*/

/*
优先队列:好像是二叉树实现的
散列表(哈希表):用哈希函数计算存储数据的地址
*/
int main()
{
    SqlList qList;
    int num[MAXSIZE] = {9, 1, 5, 8, 3, 7, 4, 6, 2, 10};
    memcpy(&qList.r[1], &num[0], MAXSIZE * sizeof(int));
    qList.length = MAXSIZE;

    //BubbleSort0(&qList);
    //BubbleSort(&qList);
    //BubbleSort1(&qList);
    //InsertSort(&qList);
    //QuickSort(&qList);
    ShellSort(&qList);
    for (auto j : qList.r)
    {
        std::cout << j << " ";
    }
    getchar();
    return 0;
}

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。