排序算法(1):插入排序,选择排序,希尔排序,堆排序

#include<iostream>
#include<assert.h>
//所有排序默认升序
using namespace std;

//普通插入排序
void InsertSort(int* array, size_t size)
{
    assert(array);
    for (size_t i = 1; i < size; ++i)
    {
        int tmp = array[i];
        int j = i - 1;
        for (; j >= 0;--j)
        {
            if (tmp < array[j])
            {
                array[j + 1] = array[j];
            }
            else
            {
                break;
            }
        }
        array[j+1] = tmp;
    }
}

二分·插入排序2
void InsertSort_P(int* array, size_t size)
{
    assert(array);

    for (size_t i = 1; i < size; ++i)
    {
        //插入第i单个元素
        int temp = array[i];
         int left = 0;
        int right = i;
            // 找位置
            while (left < right)
            {
                int mid = left + (right - left) / 2;

                if (array[mid] <= temp)
                {
                    left = mid + 1;
                }
                else
                {
                    right = mid;
                }
            }

            // 搬移数据
            for (int end = i - 1; end >= left; end--)
            {
                array[end + 1] = array[end];
            }
            array[left] = temp;
        }

}


二分·插入排序2
//void InsertSort_P(int* array, size_t size)
//{
//  assert(array);
//
//  for (int i = 1; i < size; ++i)
//  {
//      //插入第i单个元素
//      int temp = array[i];
//      int left = 0;
//      int right = i;
//
//      // 找位置
//      while (left < right)
//      {
//          int mid = left + (right - left) / 2;
//          if (array[mid] <= temp)
//          {
//              left = mid + 1;
//          }
//          else
//          {
//              right = mid;
//          }
//      }
//
//      // 搬移数据
//      for (int end = i - 1; end >= left; end--)
//      {
//          array[end + 1] = array[end];
//      }
//
//      array[left] = temp;
//  }
//}

//二分·插入排序1
void InsertSortHalf(int *arr,size_t size)
{
    assert(arr);
    for (size_t i = 1; i < size; ++i)
    {
        int tmp = arr[i];
        if (tmp < arr[i - 1])
        {
            int left = 0;
            int right = i - 1;
            //
            while (left <= right)
            {
                int mid = left + (right - left) / 2;
                if (tmp < arr[mid])
                    right = mid - 1;
                else
                    left = mid + 1;
            }
            for (int j = i - 1; j >= right + 1; --j)
                arr[j + 1] = arr[j];
            arr[right + 1] = tmp;
        }
    }
}


//希尔排序(插入排序的一种)
void ShellSort(int* array, size_t size)
{
    assert(array);
    int gap = size;
    while (gap > 1 )
    {
        gap = gap / 3 + 1;
        for (size_t i = gap; i < size; ++i)
        {
            if (array[i] < array[i - gap])
            {
                int tmp = array[i];
                int j = i - gap;
                for (; j >= 0 && tmp < array[j]; j -= gap)
                {
                    array[gap + j] = array[j];
                }
                array[j + gap] = tmp;
            }
        }
    }
}

//简单选择排序:每次找一个最值,放在最前面或者最后面,同时缩小区间
// 比较n+n-1+n-2+.. 共n(n-1)/2次 时间复杂度为O(n2);
void SelectSort(int* array, size_t size)
{
    assert(array);
    int end = size-1;
    while (--end)
    {
        int maxpos = 0;
        int i = 1;
        for (; i <= end; ++i)
        {
            if (array[i]>array[maxpos])
            {
                maxpos = i;
            }
        }
        if (end != maxpos)
            swap(array[end], array[maxpos]);
    }

}


//改进的选择排序:同时找最大值和最小值
//:这个代码是有问题的 :倘若最大值在数组最前面,最小值在数组最后面,
//那个第一次找到的最大值下标就是0,最小值下标就是size-1:
//然后执行交换,交换了两次,两个值又回到了原处,那么一开始就错了
//要改进的话,每次发现比这个min小的就直接交换即可,但是这么实现就跟选择排序的思想背道而驰故此不实现
/这是一段错误的代码/
void SelectSortDou(int* array, size_t size)
{
    assert(array);
    int end = size-1;
    int begin = 0;
    while (begin <= end)
    {
        int maxpos = end;
        int minpos = begin;

        for (int i = begin; i <= end; ++i)
        {
            if (array[i]>array[maxpos])
            {
                maxpos = i;
            }
            if (array[i]<array[minpos])
            {
                minpos = i;
            }
        }

        if (end != maxpos)
            swap(array[end], array[maxpos]);//问题出在这里
        if (begin!=minpos)
            swap(array[begin], array[minpos]);//问题出在这里
        begin++;
        end--;
    }
}

//上面是一段错误的代码///

//改进的选择排序:树形选择排序,也叫锦标赛排序(未实现)


void adjustDown(int* array, int i,int end)
{
    int child = 2 * i + 1;
    while (child <= end)
    {
        if ((child + 1 <= end) && (array[child + 1] > array[child]))
            child += 1;
        if (array[child] > array[i])
            swap(array[child], array[i]);
        i = child;
        child = child * 2 + 1;
    }
}

//对树形选择排序再进行改进:堆排序,这里要创建最大堆
void HeapSort(int* array, size_t size)
{
    assert(array);
    //对整个数组进行一次堆排列
    for (int i = (size - 1) / 2; i >= 0; --i)
    {
        adjustDown(array, i, size-1);
    }
    //每次把最大的一个放在数组后面,同时堆排序范围减少1
    for (int i = (size - 1); i > 0; --i)
    {
        swap(array[i], array[0]);
        adjustDown(array, 0, i-1);
    }
}





void pri(int *arr,size_t size)
{
    for (size_t i = 0; i < size; ++i)
    {
        cout << arr[i]<<" ";
    }
    cout << endl;
}

//这里面都是插入排序,
void test1()
{
    int arr[] = { 21, 18, 49, 25, 16, 8,21,35,99,5,21 };

    //InsertSort(arr, sizeof(arr) / sizeof(int));
    //pri(arr, sizeof(arr) / sizeof(int));

    //InsertSortHalf(arr, sizeof(arr) / sizeof(int));
    //pri(arr, sizeof(arr) / sizeof(int));

    //ShellSort(arr, sizeof(arr) / sizeof(int));
    //pri(arr, sizeof(arr) / sizeof(int));
}

//这些都是选择排序
void test2()
{
    int arr[] = { 8, 21, 35, 99, 5, 21,21, 18, 49, 25, 16, 1,19,88,53};
    //int arr[] = { 1, 5, 8, 16, 18, 19, 21, 21, 21, 25, 35, 49, 53, 88, 99 };

    //SelectSort(arr, sizeof(arr) / sizeof(int));
    //pri(arr, sizeof(arr) / sizeof(int));

    //SelectSortDou(arr, sizeof(arr) / sizeof(int));
    //pri(arr, sizeof(arr) / sizeof(int));

    //HeapSort(arr, sizeof(arr) / sizeof(int));
    //pri(arr, sizeof(arr) / sizeof(int));

}


int main()
{
    //test1();
    test2();
    system("pause");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值