排序算法的比较

这里写图片描述
1.冒泡排序(时间复杂度O(n^2),空间复杂度O(1),不稳定排序)
首先定义一个变量size_t bount=0
[0,bound)的区间已经排好序的区间,[bound,size)待排序的区间
从第二个数字开始,每一个数字都会和前一个数字进行比较,如符合则交换

void BubbleSort(int array[],size_t size)
{
     if (size == 1)
     {
         return;
     }
     size_t i = 0;
     size_t bound = 0;
     for (i = 0; i < size - 1; i++)
     {
           for (bound = 0; bound < size - 1 - i; bound++)
           {
                if (array[bound]>array[bound + 1])
                {
                     swap(&array[bound], &array[bound + 1]);
                }
           }
     }
     return;
}

2.选择排序(时间复杂度O(n^2),空间复杂度O(1),稳定排序)

void SelectSort(int *array, size_t size)
{
     if (size == 1)
     {
           return;
     }
     size_t i = 0;
     size_t j = 1;
     for (i = 0; i < size - 1; i++)
     {
           for (j = i + 1; j < size; j++)
           {
                if (array[j] < array[i])
                {
                     swap(&array[i], &array[j]);
                }
           }
     }
     return;
}

3.堆排序HeapSort(从小到大,建立大堆)(时间复杂度O(N*logN),空间复杂度O(1),稳定排序)
a.先建一个堆HeapCreate
b.再一个一个的删除堆顶元素

//建立一个大堆,若是从大到小排序的话
void AdjustDown(int array[], size_t size, size_t index)
{
     size_t parent = index;
     size_t child = parent * 2 + 1;
     //从上往下调整
     //先找出左右子树中最大的那个,若左比右小,交换
     while (child < size)
     {
           //若有右子树
           if (child + 1 < size && array[child] < array[child + 1])
           {
                child = child + 1;
           }
           if (array[child] > array[parent])
           {
                swap(&array[child], &array[parent]);
           }
           else
           {
                break;
           }
           parent = child;
           child = parent * 2 + 1;    
     }
     return;
}
void HeapPop(int array[], size_t size)
{
     swap(&array[0], &array[size - 1]);
     --size;
     AdjustDown(array, size, 0);
}
void HeapCreate(int array[], size_t size)
{
     if (array == NULL)
     {
           return;
     }
     //算出最后一个节点的父节点的下标从这开始调整
     size_t i = (size - 1 - 1) / 2;
     for (; i > 0; --i)
     {
           AdjustDown(array, size, i);
     }
     AdjustDown(array, size, 0);
}
//堆排序
void HeapSort(int array[], int size)
{
     //只有一个数字不用排序
     if (size == 1)
     {
           return;
     }
     //构建一个大堆
     HeapCreate(array, size);
     size_t i = 0;
     //
     for (; i < size - 1; ++i)
     {
           //一个一个删除堆顶元素
           HeapPop(array, size - i);
     }
     return;
}

4.插入排序(时间复杂度(O(N^2)),空间复杂度(N(1),稳定排序)
[0,bound)的区间已经排好序的区间,[bound,size)待排序的区间
每次取到一个元素就将它插入到已经排好的区间中(即线性表的插入,搬运)

//从小到大排序
void InsertSort(int array[], size_t size)
{
     if (array == NULL || size <= 1)
     {
           return;
     }
     size_t bound = 1;
     for (; bound < size; ++bound)
     {
           int value = array[bound];
           size_t i = bound;
           for (; i>0; --i)
           {
                //因为前面已经有序,现在就是判断它需不需要搬运就是调整
                if (array[i-1] > value)
                {
                     array[i] = array[i - 1];
                }
                else
                {
                     break;
                }
           }
           array[i] = value;
     }
     return;
}

5.希尔(shell)排序(时间复杂度(O(N^2)))
就是将数据根据步长分为若干组

步长为4(分为2组)
将第一个组的第一个元素和第二个组的第一个元素比较若大,则交换,然后会第一个组的第二个元素和第二组的第二个元素…
步长为2(分为四组)
依旧进行比较
画一画就明白了

这里写图片描述

void ShellSort(int array[], size_t size)
{
     if (size <= 1)
     {
           return;
     }
     //先生成步长序列
     size_t gap = size / 2;
     for (; gap > 0; gap /= 2)
     {
           size_t bound = gap;
           for (; bound < size;bound++)
           {
                size_t i = bound;
                for (; i>gap; i -= gap)
                {
                     if (array[i - gap] > array[i])
                     {
                           swap(&array[i], &array[i - gap]);
                     }
                }
           }
     }
}

对于插入排序来说如果序列已经基本有序,那么插入排序的速度非常快
如果元素个数肥肠少,那么插入排序的速度也非常快

6归并排序
先划分子区间,然后在两个两个区间的有序合并

这里写图片描述

递归版本(其实就是划分区间部分需要递归)
非递归版本(手动划分区间)


void _MergeArray(int array[], size_t beg, size_t mid, size_t end, int *tmp)
{
     size_t cur1 = beg;
     size_t cur2 = mid;
     size_t tmp_index = beg;
     while (cur1 < mid&&cur2 < end)
     {
           //将这两个区间里较小的数放入一个新开辟的空间里
           if (array[cur1] < array[cur2])
           {
                tmp[tmp_index++] = array[cur1++];
           }
           else
           {
                tmp[tmp_index++] = array[cur2++];
           }
     }
     //处理一个完了另外一个剩下的情况,下面这两个只有一个生效
     while (cur1 < mid)
     {
           tmp[tmp_index++] = array[cur1++];
     }
     while (cur2 < end)
     {
           tmp[tmp_index++] = array[cur2++];
     }
     //将tmp里的元素拷回到array里
     //从那开始,从哪结束,拷贝多少个字节
     memcpy(array + beg, tmp + beg, sizeof(int)*(end - beg));
}

//递归版本
void _MergeSort(int array[], size_t beg, size_t end, int *tmp)
{
     if (end - beg <= 1)
     {
           return;
     }
     //先划分有序区间
     size_t mid = beg + (end - beg) / 2;
     //递归的划分子区间
     _MergeSort(array, beg, mid, tmp);
     _MergeSort(array, mid, end, tmp);
     //要先保证左右区间为有序之后才能进行合并
     _MergeArray(array, beg, mid, end, tmp);
}

void MergeSort(int array[], size_t size)
{
     if (size <= 1)
     {
           return;
     }
     int *tmp = (int *)malloc(sizeof(int)*size);
     _MergeSort(array, 0, size, tmp);
     free(tmp);
}


//非递归版本
//其实就是手动的划分子区间
void MergeSortByLoop(int array[], size_t size)
{
     if (size <= 1)
     {
           return;
     }
     int *tmp = (int *)malloc(sizeof(int)*size);
     //先划分区间,再有序合并

     //此为手动划分区间部分
     size_t gap = 1;
     for (; gap < size; gap *= 2)
     {
           //进行有序合并
           size_t i = 0;
           for (; i < size; i += 2 * gap)
           {
                int beg = i;//区间开始
                int mid = i+gap;//第二个区间的开始
                int end = i + gap * 2;//总处理区间的结束
                if (mid>size)
                {
                     mid = size;
                }
                if (end > size)
                {
                     end = size;
                }
                _MergeArray(array, beg, mid, end, tmp);
           }
     }
}

7.快速排序
定义一个标杆一般是数组最后一个元素
定义两个left,right指针,分别指向数组第一个元素和最后一个元素,left向后走,right向前走,当left指针指向第一个比标杆大的元素,right指向读一个比标杆小的元素,则交换这两个指针所代表的元素,直到这两个指针重合,则将这个指针和标杆元素交换,此时标杆左边都是比它小的元素,标杆元素右边都是比它大的元素,然后在对这两边的数组在分别进行排序

这里写图片描述

//交换法
int Partion1(int array[], size_t beg, size_t end)
{
     size_t left = beg;
     size_t right = end - 1;//最后一个元素
     int key = array[right];
     while (left < right)
     {
           //不对
           /*while (array[left++] <= key&&array[right--] >= key&&left < right)
           {
                swap(&array[left], &array[right]);
           }*/
           while (left<right&&array[left]<=key)
           {
                ++left;
           }
           while (left<right&&array[right]>=key)
           {
                --right;
           }
           if (left < right)
           {
                swap(&array[left], &array[right]);
           }
     }
     //交换基准值和此时的left指针
     swap(&array[left], &array[end - 1]);
     return left;
}
//挖坑法
int Partion2(int array[], size_t beg, size_t end)
{
     size_t left = beg;
     size_t right = end - 1;
     int key = array[right];
     while (left<right)
     {
           //从左到右先找到一个大于基准值的元素
           while (left < right&&array[left] <= key)
           {
                left++;
           }
           if (left < right)
           {
                //将找到的这个left值填到right里
                array[right--] = array[left];
           }
           //从右往左找倒一个小于基准值的元素
           while (left < right&&array[right] >= key)
           {
                --right;
           }
           if (left < right)
           {
                array[left++] = array[right];
           }
     }
     array[left] = key;
     return left;
}
void _QuickSort(int array[], size_t beg, size_t end)
{
     if (end - beg <= 1)
     {
           return;
     }
     //Partion函数的作用是对当前的[beg,end)区间进行整理
     //整理成以某个基准值为中心,左边都比它小,右边都比它
     //返回值hi返回基准值所在下标
     int mid = Partion1(array, beg, end);
     Partion1(array, beg, mid);
     Partion1(array, mid, end);
}
//快速排序
void QuickSort(int array[], size_t size)
{
     if (size <= 1)
     {
           return;
     }
     _QuickSort(array, 0, size);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值