数据结构中的几种排序算法

1.直接插入排序

直接插入排序的基本思想是将整个待排序表看成左右两个部分,其中左边为有序区,右边为无序区,排序过程就是把无序区的数据插入到有序区,以构成新的有序区。

即将R[i]插入到有序序列R[1..i-1],使记录的有序序列从R[1..i-1]变为R[1..i]。

代码实现如下:

void insertSort(int a[], int size)
{
    int temp;
    for (int i = 1; i < size; i++)
    {
        temp = a[i];
        int j = i-1;
        while (a[j] > temp)
        {
            a[j+1] = a[j];
            j--;
        }
        a[j+1] = temp;
    }
}

直接插入排序是稳定的排序,最小时间复杂度为O(n),最大时间复杂度为O(n²)。

2.折半插入排序

折半插入排序与直接插入排序相比,采用二分查找的方式确定插入位置,减少了关键字比较的次数。

代码实现如下:

void binSort(int a[], int size)
{
    int temp;
    for (int i = 1; i < size; i++)
    {
        temp = a[i];
        int l = 0, r = i-1;
        while (r > l)
        {
            temp = a[i];
            int mid = (l+r)/2;
            if (temp > a[mid])
                l = mid+1;
            else
                r = mid-1;
        }
        for (int j = i-1; j >= r+1; j--)
            a[j+1] = a[j];
        a[r+1] = temp;
    }
}

时间复杂度同样为O(n²)。

3.希尔排序

希尔排序的基本思想是:将待排序列划分为若干组,在每组内进行直接差入排序,当每组序列基本有序后,再对整个序列进行直接插入排序。

希尔排序的关键是如何分组,我这里采用间隔方法分组,分组方法为:给定一个步长d,将下标相差为d的倍数的元素放一组,得到d组。d的典型取值为d1 = n/2, d2 = d1/2, d3 =

d2/2, ... , 1,当d = 1时,整个序列在一组内执行直接插入排序,此时只需要较少的比较和移动次数。

代码实现如下:

void shellSort(int a[], int size)
{
    int temp;
    int dh = size/2;
    while (dh > 0)
    {
         for (int i = dh; i < n; i++)
         {
              temp = a[i];
              int j = i - dh;
              while (j >= 0 && a[j] > temp)
              {
                   a[j+dh] = a[j];
                   j = j -dh;
              }
              a[j+dh] = temp;
         }
         dh = dh/2;
    }
}

希尔排序每一趟都是在上一趟的基础上进行的,各趟的时间复杂度为O(n),所需趟数为log2(n),故整个排序的时间复杂度为O(nlog2(n))。该算法是不稳定算法。

4.冒泡排序

冒泡排序的基本思想是:从一端开始,逐个比较相邻的两个元素,发现倒序即交换。典型的做法是从后往前逐个比较相邻的两个元素,发现倒序即交换。

代码实现如下:

void bubbleSort(int a[], int size)
{
    for (int i = 0; i < size-1; i++)
        for (int j = size-1; j > i; j--)
            if (a[j] > a[j-1])
            {
                int temp = a[j];
                a[j] = a[j-1];
                a[j-1] = temp;
            }
}

如果在某一趟排序过程中,没有进行任何交换,那么数据已经有序,就可以结束排序,其时间复杂度可以达到O(n)。为实现这一要求,在每趟排序中设置是否交换的标志,这样

可以得到改进的冒泡排序如下:

void bubbleSort(int a[], int size)
{
   int i = 0;
    bool exchanged = true;
    do
    {
        exchanged = false;
       for (int j = size-1; j > i; j--)

            if (a[j] > a[j-1])
            {
                int temp = a[j];
                a[j] = a[j+1];
                a[j+1] = temp;
               exchanged = true;
            }

 i++;
}while (i < size-1 && exchanged = true);
}

5.快速排序

快速排序的基本思想是:首先选定一个元素作为中间元素,然后将数表中所有元素与该中间元素相比较,将表中比中间元素小的元素调到表的前面,比中间元素大的调到后面,

再将中间数放在两部分之间作为一个分界点,由此得到一个划分。对左右两部分分别进行快速排序,直到每个子表仅有一个元素或为空表。

这里以第一个数为中间数,代码实现如下:

void quickSort(int a[], int l, int r)
{
    if (l < r)
    {
        int i = l, j = r, x = a[l];
        while (i < j)
        {
            while(i < j && a[j]>= x) // 从右向左找第一个小于x的数
                j--;
            if(i < j)
                a[i++] = a[j];
            while(i < j && a[i]< x) // 从左向右找第一个大于等于x的数
                i++;
            if(i < j)
                a[j--] = a[i];
        }
        a[i] = x;
        quickSort(a, l, i - 1); // 递归调用
        quickSort(a, i + 1, r);
    }
}

快速排序显然是不稳定排序。快速排序完成一次排序共需log2(n)趟,每一趟划分所需时间可认为是cn(c为常数)。因而可认为快速排序的平均时间复杂度为O(knlog2(n))。

6.直接选择排序

直接选择排序很简单:通过在待排序子表中比较一遍得到最大(小)元素,再将该元素放在子表的最后(前)面。

void selectSort(int a[], int size)
{
    for (int i = 0; i < size-1; i++)
    {
        int min = i;
        for (int j = i+1; j < size; j++)
        {
            if (a[j] < a[min])
                min = j;
        }
        if (a[i] != a[min])
        {
            temp = a[min];
            a[min] = a[i];
            a[i] = temp;
        }
    }
}

直接选择排序是不稳定排序,时间复杂度为O(n²)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值