(二)排序

1、分类

2、时间复杂度

3、详细阐述

(1) 冒泡排序

从下往上两两比较,如果有n个元素需要比较n-1次,每一轮减少1次比较。

void BubbleSort(int k[], int n) {
  for (int i = 0; i < n - 1; i++)
    for (int j = i + 1; j < n; j++)
      if (k[i] > k[j]) {
        int temp = k[i];
        k[i] = k[j];
        k[j] = temp;
      }
}

void BubbleSort(int k[], int n) {
  for (int i = 0; i < n - 1; i++)
    for (int j = n - 1; j > i; j--)
      if (k[j - 1] > k[j]) {
        int temp = k[j - 1];
        k[j - 1] = k[j];
        k[j] = temp;
      }
}

void BubbleSort(int k[], int n) {
  int flag = 1;
  for (int i = 0; i < n - 1 && flag; i++)
    for (int j = n - 1; j > i; j--) {
      flag = 0;
      int temp = k[j - 1];
      k[j - 1] = k[j];
      k[j] = temp;
    }
}

(2) 选择排序:比较第一个元素与后续元素做比较,小放前面

void SelectSort(int k[], int n) {
  for (int i = 0; i < n - 1; i++) {
    int min = i;
    for (int j = i + 1; j < n; j++) {
      if (k[j] < k[min]) min = j;
    }
    if (min != i) {
      int temp = k[min];
      k[min] = k[i];
      k[i] = temp;
    }
  }
}

(3) 直接插入排序:假定前i个构成的子序列是处于已排序的情况下进行排序的,然后将第i个元素与前i构成的子序列逆序进行比较,如果是要升序排序,则比较第i个元素是否比j=i-1(i-1需要>=0)的元素大,如果是则第i个元素的位置(即j+1的位置上)保持不动,反之则将j=i-1的元素放置到i的位置,再进行第i个元素与j=i-2(i-2需要>=0)的,依次进行,如果第i个元素刚好比j=i-3大,则将第i个元素插入到j=i-2(即j+1的位置)上。

void InsertSort(int k[], int n) {
  for (int i = 1; i < n; i++)
    if (k[i] < k[i - 1]) {
      int temp = k[i];
      for (j = i - 1; k[j] > temp; j--) k[j + 1] = k[j];
      k[j + 1] = temp;
    }
}

(4) 希尔排序

把记录按步长gap分组,对每组记录采用直接插入顺序方法进行排序。随着步长逐渐减少,所分成的组包含的记录越來越多,当步长的值减少到1时,整个数据合成为一组,构成一组有序记录,则完成排序。

void InsertSort(int k[], int n) {
  int i, j, temp;
  int gap = n;
  do {
    gap = gap / 3 + 1;
    for (i = gap; i < n; i++) {
      if (k[i] < k[i - gap]) {
        temp = k[i];
        for (j = i - gap; k[j] > temp; j -= gap) k[j + gap] = k[j];
        k[j + gap] = temp;
      }
    }
  } while (gap > 1);
}

(5) 堆排序

根结点一定是堆中所有结点最大或最小者,如果按照层序遍历的方式给结点从1开始编号。

ki >=k2i且ki>=k2i+1、ki<=k2i且ki<=k2i+1;下标i与2i和2i+1是双亲和子女关系。

void swap(int k[], int i, int j) {
  int temp;
  temp = k[i];
  k[i] = k[j];
  k[j] = temp;
}
void HeapAdjust(int k[], int s, int n) {
  int i, temp;
  temp = k[s];
  for (i = 2 * s; i <= n; i *= 2) {
    if (i < n && k[i] < k[i + 1]) i++;
    if (temp >= k[i]) break;
    k[s] = k[i];
    s = i;
  }
  k[s] = temp;
}
void HeapSort(int k[], int n) {
  int i;
  for (i = n / 2; i > 0; i--) HeapAdjust(k, i, n);
  for (i = n; i > 1; i--) {
    swap(k, 1, i);
    HeapAdjust(k, 1, i - 1);
  }
}

(6) 归并排序

利用归并的思想实现的排序方法。假设初始序列有n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,如此重复,直至得到一个长度为n的有序序列为止,这种排序方法称为2路归并排序。

#define MAXSIZE 10
void merging(int *list1, int list1_size, int *list2, int list2_size) {
  int i, j, k, m;
  int temp[MAXSIZE];
  i = j = k = 0;
  while (i < list1_size && j < list2_size) {
    if (list1[i] < list2[j])
      temp[k++] = list1[i++];
    else
      temp[k++] = list2[j++];
  }
  while (i < list1_size) temp[k++] = list1[i++];
  while (j < list2_size) temp[k++] = list2[j++];
  for (m = 0; m < (list1_size + list2_size); m++) list1[m] = temp[m];
}

void MergeSort(int k[], int n) {
  if (n > 1) {
    int *list1 = k;
    int list1_size = n / 2;
    int *list2 = k + n / 2;
    int list2_size = n - list1_size;
    MergeSort(list1, list1_size);
    MergeSort(list2, list2_size);
    merging(list1, list1_size, list2, list2_size);
  }
}

(7) 快速排序

首先在要排序的序列a中选取一个中轴值,而后将序列分成两个部分,其中左边的部分b中的元素均小于或者等于中轴值,右边的部分c的元素均大于或者等于中轴值,而后通过递归调用快速排序的过程分别对两个部分进行排序,最后将两部分产生的结果合并即可得到最后的排序序列。

void swap(int k[], int low, int high) {
  int temp;
  temp = k[low];
  k[low] = k[high];
  k[high] = temp;
}
int Partition(int k[], int low, int high) {
  int point;
  point = k[low];
  while (low < high) {
    while (low < high && k[high] >= point) high--;
    swap(k, low, high);
    while (low < high && k[low] <= point) low++;
    swap(k, low, high);
  }
  return low;
}
void QSort(int k[], int low, int high) {
  int point;
  if (low < high) {
    point = Partition(k, low, high);
    QSort(k, low, point - 1);
    QSort(k, point + 1, high);
  }
}
void QuickSort(int k[], int n) { QSort(k, 0, n - 1); }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值