排序(Sort)(二)

简介: 排序(Sort)(二)

一、冒泡排序

1、步骤

左边大于右边交换一趟排下来最大的在右边

2、思路

动图演示如下:

3、代码实现

void BubbleSort(int* a, int n)
{
  int exchange = 0;
  for (int i = 0; i < n - 1; i++)
  {
    for (int j = 0; j < n - 1 - i; j++)
    {
      if (a[j] > a[j + 1])
      {
        Swap(&a[j], &a[j + 1]);
        exchange = 1;
      }
    }
    if (exchange == 0)
    {
      break;
    }
  }
}

4、特性总结

1、时间复杂度:O(N^2)

2、空间复杂度O(1)

3、稳定性:稳定

5、实现结果

二、快速排序

1、步骤

任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。

2、思路

hoare版(左右指针法)

挖坑法

前后指针法

3、代码实现

三数取中对代码进行优化

void GetMid(int* a, int left, int right)
{
  int mid = (left + right) / 2;
  if (a[left] < a[mid])
  {
    if (a[mid]<a[right])
    {
      return mid;
    }
    else if (a[left] < a[right])//mid最大
    {
      return right;
    }
    else
    {
      return left;
    }
  }
  //a[left] > a[mid]
  else
  {
    if (a[mid] > a[right])
    {
      return mid;
    }
    else if (a[left] > a[right])//mid最小
    {
      return right;
    }
    else
    {
      return left;
    }
  }
}

快排优化

减少递归调用函数开辟的空间

void QuickSort(int* a, int begin, int end)
{
  if (begin >= end)
    return;
  if (end - begin + 1 > 10)
  {
    int keyi = PartSort3(a, begin, end);
    QuickSort(a, begin, keyi - 1);
    QuickSort(a, keyi + 1, end);
  }
  else
  {
    Insertsort(a + begin, end - begin + 1);
  }
}

hoare(左右指针法)

//hoare版
int PartSort1(int* a, int left, int right)
{
  int midi = GetMidi(a, left, right);
  Swap(&a[midi], &a[left]);
  int keyi = left;
  while (left < right)
  {
    //找小
    while (left < right && a[right] >= a[keyi])
    {
      --right;
    }
    //找大
    while (left < right && a[left] <= a[keyi])
    {
      ++left;
    }
    Swap(&a[left], &a[right]);
  }
  Swap(&a[keyi], &a[left]);
  return left;
}
void QuickSort(int* a, int begin, int end)
{
  if (begin >= end)
    return;
  if (end - begin + 1 > 10)
  {
    int keyi = PartSort3(a, begin, end);
    QuickSort(a, begin, keyi - 1);
    QuickSort(a, keyi + 1, end);
  }
  else
  {
    Insertsort(a + begin, end - begin + 1);
  }
}

挖坑法

//挖坑法
int PartSort2(int* a, int left, int right)
{
  int midi = GetMidi(a, left, right);
  Swap(&a[midi], &a[left]);
  int key = a[left];
  int hole = left;
  while (left < right)
  {
    while (left < right && a[right] >= key)
    {
      right--;
    }
    a[hole] = a[right];
    hole = right;
    while (left < right && a[left] <= key)
    {
      left++;
    }
    a[hole] = a[left];
    hole = left;
  }
  a[hole] = key;
  return left;
}
void QuickSort(int* a, int begin, int end)
{
  if (begin >= end)
    return;
  if (end - begin + 1 > 10)
  {
    int keyi = PartSort3(a, begin, end);
    QuickSort(a, begin, keyi - 1);
    QuickSort(a, keyi + 1, end);
  }
  else
  {
    Insertsort(a + begin, end - begin + 1);
  }
}

前后指针法

//前后指针法
int PartSort3(int* a, int left, int right)
{
  int midi = GetMidi(a, left, right);
  Swap(&a[midi], &a[left]);
  int keyi = left;
  int prev = left;
  int cur = left + 1;
  while (cur <= right)
  {
    if (a[cur] < a[keyi]&& prev++ != cur)
    {
      Swap(&a[cur], &a[prev]);
    }
    ++cur;
  }
  Swap(&a[keyi], &a[prev]);
  return prev;
}
void QuickSort(int* a, int begin, int end)
{
  if (begin >= end)
    return;
  if (end - begin + 1 > 10)
  {
    int keyi = PartSort3(a, begin, end);
    QuickSort(a, begin, keyi - 1);
    QuickSort(a, keyi + 1, end);
  }
  else
  {
    Insertsort(a + begin, end - begin + 1);
  }
}

非递归实现

借助栈实现

//快排非递归
void QuickSortNonR(int* a, int begin, int end)
{
  ST st;
  STInit(&st);
  STPush(&st, end);
  STPush(&st, begin);
  while (!STEmpty(&st))
  {
    int left = STTop(&st);
    STPop(&st);
    int right = STTop(&st);
    STPop(&st);
    int keyi = PartSort1(a,left, right);
    if (keyi + 1 < right)
    {
      STPush(&st, right);
      STPush(&st, keyi+1);
    }
    if (left<keyi-1)
    {
      STPush(&st, keyi-1);
      STPush(&st, left);
    }
  }
  STDestroy(&st);
}

4、特性总结

1、时间复杂度:O(N*logN)

2、空间复杂度:O(logN)

3、稳定性:不稳定 例如:5 0 5 7 10 5 8

5、实现结果

三、归并排序

1、步骤

分解:将待排序的数组不断分成两个子数组,直到每个子数组只有一个元素为止。

合并:将相邻的两个子数组合并成一个有序数组,直到最后只剩下一个有序数组为止

2、思路

动图演示如下:

3、代码实现

递归实现

void _MergeSort(int* a, int* tmp, int begin, int end)
{
  if (end <= begin)
    return;
  int mid = (end + begin) / 2;
  _MergeSort(a, tmp, begin, mid);
  _MergeSort(a, tmp, mid + 1, end);
  int begin1 = begin, end1 = mid;
  int begin2 = mid + 1, end2 = end;
  int index = begin;
  while (begin1 <= end1 && begin2 <= end2)
  {
    if (a[begin1] < a[begin2])
    {
      tmp[index++] = a[begin1++];
    }
    else
    {
      tmp[index++] = a[begin2++];
    }
  }
  while (begin1 <= end1)
  {
    tmp[index++] = a[begin1++];
  }
  while (begin2 <= end2)
  {
    tmp[index++] = a[begin2++];
  }
  memcpy(a + begin, tmp + begin, (end - begin + 1) * sizeof(int));
}
void MergeSort(int* a, int n)
{
  int* tmp = (int*)malloc(sizeof(int) * n);
  _MergeSort(a, tmp, 0, n - 1);
  free(tmp);
}

非递归实现

void MergeSortNonR(int* a, int n)
{
  int* tmp = (int*)malloc(sizeof(int) * n);
  if (tmp == NULL)
  {
    perror("malloc fail");
    return;
  }
  int gap = 1;
  while (gap < n)
  {
    for (int i = 0; i < n; i += 2 * gap)
    {
      int begin1 = i, end1 = i + gap - 1;
      int begin2 = i + gap, end2 = i + 2 * gap - 1;
      if (end2 >= n)
      {
        end2 = n - 1;
      }
      if (end1 >= n  &&  begin2 >= n)
      {
        break;
      }
      int index = i;
      while (begin1 <= end1 && begin2 <= end2)
      {
        if (a[begin1] < a[begin2])
        {
          tmp[index++] = a[begin1++];
        }
        else
        {
          tmp[index++] = a[begin2++];
        }
      }
      while (begin1 <= end1)
      {
        tmp[index++] = a[begin1++];
      }
      while (begin2 <= end2)
      {
        tmp[index++] = a[begin2++];
      }
      memcpy(a + i, tmp + i, (end2-i+1) * sizeof(int));
    }
    gap *= 2;
  }
  free(tmp);
}

4、特性总结

时间复杂度:O(N*logN)

空间复杂度:O(N)

稳定性:稳定

5、实现结果

四、计数排序

1、步骤

1、统计相同元素出现次数

2、根据统计的结果将序列回收到原数组中

2、思路

动图演示如下:

3、代码实现

void CountSort(int* a, int n)
{
  int min = a[0], max = a[0];
  for (int i = 0; i < n; i++)
  {
    if (a[i] < min)
      min = a[i];
    if (a[i] > max)
      max = a[i];
  }
  int range = max - min + 1;
  int* count = (int*)malloc(sizeof(int) * range);
  if (count == NULL)
  {
    perror("malloc fail");
    return;
  }
  memset(count, 0, sizeof(int) * range);
  // 统计数据出现次数
  for (int i = 0; i < n; i++)
  {
    count[a[i] - min]++;
  }
  // 排序
  int j = 0;
  for (int i = 0; i < range; i++)
  {
    while (count[i]--)
    {
      a[j++] = i + min;
    }
  }
}

4、特性总结

1、时间复杂度:O(N+range)

2、空间复杂度:O(range)

3、稳定性:稳定

5、实现结果


总结

目录
相关文章
|
2月前
|
搜索推荐 算法 Java
sort-05-insert sort 插入排序算法详解
这是一个关于排序算法的系列文章总结,包括冒泡排序、快速排序、选择排序、堆排序、插入排序等10种排序算法的详细讲解和Java实现。插入排序是一种简单直观的排序算法,通过构建有序序列并逐个插入新元素来排序。提供的Java代码展示了插入排序的实现过程,并附有测试示例。所有算法已开源在GitHub项目[https://github.com/houbb/sort](https://github.com/houbb/sort)中。
|
2月前
排序——sort的用法
排序——sort的用法
14 0
|
2月前
|
搜索推荐 数据库 C++
带用排序等法sort讲解
带用排序等法sort讲解
13 0
|
12月前
|
搜索推荐 C++
C++利用sort进行排序
C++利用sort进行排序
|
2月前
|
搜索推荐
实现bubble_sort冒泡排序函数,排序任意类型数据
实现bubble_sort冒泡排序函数,排序任意类型数据
37 0
|
2月前
|
C++
C++如何进行sort的使用——C++如何进行排序
C++如何进行sort的使用——C++如何进行排序
32 0
|
2月前
|
小程序
排序sort()排序用法
排序sort()排序用法
|
8月前
排序(Sort)(一)
排序(Sort)(一)
57 0
sort() 函数按照字符串顺序对值进行排序。
sort() 函数按照字符串顺序对值进行排序。
145 0
|
数据库 开发者 索引
排序 sort|学习笔记
快速学习排序 sort。
221 0
排序 sort|学习笔记