首页 > 代码库 > 排序(一)

排序(一)

(一) 插入排序(insertion sort): 是最简单的排序算法之一,插入排序由 N - 1 趟排序组成。对于 P = 1 趟到 P = N - 1 趟,插入排序保证从位置 0 到 位置 P 的元素为已排序状态。一般方法:在第 P 趟,将位置P 上的元素向左移动到它在前P + 1 个元素中的正确位置上。(位置P 上的元素暂存于 tmp 中,而(在位置 P 之前)所有更大的元素都被向右移动一个位置。然后 tmp 被置于正确的位置上。)

void InsertSort(ElemType A[], int N)        //N为数组长度
{
 int j, P;
 ElemType temp;
 for(P = 1; P < N; P++)
 {
  temp = A[P];
  for(j = P; j > 0 && A[j - 1] > temp; j--)
   A[j] = A[j - 1];
  A[j] = temp;
 }
}

插入排序分析:由于嵌套循环的每一个都花费N 次迭代,因此插入排序为 O(N^2),而且这个界是精确的,因为以反序输入可以达到该界。

(二) 希尔排序(ShellSort):该算法是冲破二次时间屏障的第一批算法之一。它通过相聚一定间隔的元素来工作;各趟比较所用的距离随着算法的进行不断减小,直到只比相邻元素的最后一趟排序为止。

希尔排序使用一个序列 h1, h2, ... , hk ,叫做增量序列。只要 h1 = 1,任何增量序列都是可行的,不过,有些增量序列比另一些要好。在使用增量 hk的一趟排序之后,对于每一个 i 有A[i] <= A[i + hk] ;所有相隔hk 的元素都被排序。此时称文件为 hk-排序的。 希尔排序的一个重要性质是,一个 hk-排序的文件保持它的 hk-排序性。一趟 hk- 排序的作用就是对 hk 个独立的子数组执行一次插入排序的过程。

//2.希尔排序【取希尔增量:N / 2 (下取整)】
void ShellSort(ElemType A[], int N)
{
 int i, j, Increment;
 ElemType temp;
 for(Increment = N / 2; Increment > 0; Increment /= 2)
 {
  for(i = Increment; i < N; i++)
  {
   temp = A[i];
   for(j = i; j >= Increment; j -= Increment)
    if(A[j - Increment] > temp)
     A[j] = A[j - Increment];
    else
     break;
   A[j] = temp;
  }
 }
}

使用希尔增量时希尔排序的最坏情形运行时间为 O(N^2)。其问题在于:这些增量对未必互素,因此较小的增量可能影响很小。

Hibbard提出一个稍微不同的增量序列: 1, 3, 7,... , 2^k - 1 。使用Hibbard 增量时希尔排序的最坏情形运行时间为

O(N^(3/2)).

(三) 冒泡排序:

//3.冒泡排序(一般思维:不完全符合冒泡排序的含义)两两比较相邻元素
void BubbleSort_1(ElemType A[], int N)
{
 int i, j, temp;
 for(i = 0; i < N - 1; i++)
 {
  for(j = i + 1; j < N; j++)
  {
   if(A[j] < A[i])
   {
    temp =A[i];
    A[i] = A[j];
    A[j] = temp;
   }
  }
 }
}
/*
 两两:是相邻的两个元素的意思
 如果有n 个元素需要比较n - 1次,每一轮减少一次比较
 所谓冒泡排序就是从下往上两两比较
*/
void BubbleSort_2(ElemType A[], int N)
{
 int i, j, temp, flag;
 flag = 1;
 for(i = 0; i < N - 1 && flag; i++)  //flag = 0时表示在该趟冒泡中没有元素进行交换,

                                                        //即已经为排好序的序列,可以减少比较次数
 {
  for(j = N - 1; j > i; j--)
  {
   flag = 0;
   if(A[j - 1] > A[j])   //两两比较
   {
    temp =A[j - 1];
    A[j - 1] = A[j];
    A[j] = temp;
    flag = 1;
   }
  }
 }
}

冒泡排序为O(N^2)。

全部代码:

//各种排序算法
#include<iostream>
using namespace std;

typedef int ElemType;
//1.插入排序
void InsertSort(ElemType A[], int N)
{
 int j, P;
 ElemType temp;
 for(P = 1; P < N; P++)
 {
  temp = A[P];
  for(j = P; j > 0 && A[j - 1] > temp; j--)
   A[j] = A[j - 1];
  A[j] = temp;
 }
}

//2.希尔排序【取希尔增量:N / 2 (下取整)】
void ShellSort(ElemType A[], int N)
{
 int i, j, Increment;
 ElemType temp;
 for(Increment = N / 2; Increment > 0; Increment /= 2)
 {
  for(i = Increment; i < N; i++)
  {
   temp = A[i];
   for(j = i; j >= Increment; j -= Increment)
    if(A[j - Increment] > temp)
     A[j] = A[j - Increment];
    else
     break;
   A[j] = temp;
  }
 }
}

//3.冒泡排序(一般思维:不完全符合冒泡排序的含义)两两比较相邻元素
void BubbleSort_1(ElemType A[], int N)
{
 int i, j, temp;
 for(i = 0; i < N - 1; i++)
 {
  for(j = i + 1; j < N; j++)
  {
   if(A[j] < A[i])
   {
    temp =A[i];
    A[i] = A[j];
    A[j] = temp;
   }
  }
 }
}
/*
 两两:是相邻的两个元素的意思
 如果有n 个元素需要比较n - 1次,每一轮减少一次比较
 所谓冒泡排序就是从下往上两两比较
*/
void BubbleSort_2(ElemType A[], int N)
{
 int i, j, temp, flag;
 flag = 1;
 for(i = 0; i < N - 1 && flag; i++)  //flag = 0时表示在该趟冒泡中没有元素进行交换,

                                                    //即已经为排好序的序列,可以减少比较次数
 {
  for(j = N - 1; j > i; j--)
  {
   flag = 0;
   if(A[j - 1] > A[j])   //两两比较
   {
    temp =A[j - 1];
    A[j - 1] = A[j];
    A[j] = temp;
    flag = 1;
   }
  }
 }
}

int main()
{
 int arr[10] = {5, 2, 8, 6, 3, 1, 7, 9, 4, 10};
 //InsertSort(arr, 10);
 //ShellSort(arr, 10);
 BubbleSort_2(arr, 10);

 for(int i = 0; i < 10; i++)
  cout << arr[i] << " ";
 cout << endl;

 system("pause");
 return 0;
}

 

排序(一)