首页 > 其他分享 >插入排序:直接插入排序、折半插入排序、希尔排序的实现

插入排序:直接插入排序、折半插入排序、希尔排序的实现

时间:2023-08-29 14:58:20浏览次数:46  
标签:折半 int series 插入排序 len gap 排序

直接插入排序

定义:直接插入排序是一种最简单的排序方法,其基本操作是将一条记录插入到已排好序的有序表中,从而得到一个新的、记录数量增 1 的有序表。

算法的代码:

#include <stdio.h>
#include <stdlib.h>


void print_series(const int series[], int len)
{
    for (int i = 0; i < len; i++)
    {
        printf("%d ", series[i]);
    }
    printf("\n");
}

void straight_insertion_sort(int s[], int len)
{
    for (int i = 1; i < len; i++)
    {
        int temp = s[i];
        int j;
        for (j = i - 1; j >= 0 && temp < s[j]; j--)
        {
            s[j+1] = s[j];
        }
        s[j + 1] = temp;
    }
}

int main(void)
{
    int series[] = {5, 7, 6, 8, 9, 2, 1, 4, 3};
    int len = sizeof(series) / sizeof(series[0]);

    // 排序前,打印
    printf("排序前,打印\n");
    print_series(series, len);

    // 排序
    straight_insertion_sort(series, len);
   
    // 排序后,打印
    printf("排序后,打印\n");
    print_series(series, len);

    return 0;
}

时间复杂度:\(O(n^2)\)

空间复杂度:\(O(1)\)

特点:

1)稳定排序
2)算法简便,且容易实现
3)即适用顺序存储结构,也适用链式存储结构,只是在单链表上无需移动记录,只需修改相应的指针

折半插入排序

定义:折半插入排序是直接插入排序的改进,通过在已经有序的序列(默认序列第一个元素为有序序列)中利用 二分查找 快速定位插入位置,这样经过n-1趟插入就能完成排序,当元素较多时,就平均性能来说,折半插入排序效率更优于直接插入排序

算法的代码:

#include <stdio.h>
#include <stdlib.h>


void print_series(const int series[], int len)
{
    for (int i = 0; i < len; i++)
    {
        printf("%d ", series[i]);
    }
    printf("\n");
}

void binary_insertion_sort(int s[], int len)
{
    for (int i = 1; i < len; i++)
    {
        int temp = s[i];
        int low = 0, high = i - 1;
        while (low <= high)
        {
            int m = (low + high) / 2;
            if (temp < s[m])
                high = m - 1;
            else
                low = m + 1;
        }
        for (int j = i - 1; j >= high + 1; j--)
        {
            s[j + 1] = s[j];
        }
        s[high + 1] = temp;
    }
}

int main(void)
{
    int series[] = {5, 7, 6, 8, 9, 2, 1, 4, 3};
    int len = sizeof(series) / sizeof(series[0]);

    // 排序前,打印
    printf("排序前,打印\n");
    print_series(series, len);

    // 排序
    binary_insertion_sort(series, len);
   
    // 排序后,打印
    printf("排序后,打印\n");
    print_series(series, len);

    return 0;
}

时间复杂度:\(O(n^2)\)

空间复杂度:\(O(1)\)

特点:
1)稳定排序
2)只适用于顺序存储结构
3)适合初始记录无序,n较大时的情况

希尔排序

定义:希尔排序是直接插入排序的改进,又称 "缩小增量排序"

算法的代码:

#include <stdio.h>
#include <stdlib.h>


void print_series(const int series[], int len)
{
    for (int i = 0; i < len; i++)
    {
        printf("%d ", series[i]);
    }
    printf("\n");
}

void shell_insert(int s[], int len, int i, int gap)
{
    for (int j = i + gap; j < len; j = j + gap)
    {
        if (s[j] < s[j - gap])
        {
            int temp = s[j];
            int k = j - gap;
            while (k >= 0 && s[k] > temp)
            {
                s[k + gap] = s[k];
                k = k - gap;
            }
            s[k + gap] = temp;
        }
    }
}

void shell_sort(int s[], int len)
{
    int gap; // 步长

    // 每一轮步长减半(也可采取其它步长方法)
    for (gap = len / 2; gap > 0; gap = gap / 2)
    {
        for (int i = 0; i < gap; i++)
            shell_insert(s, len, i, gap);
    }
}

int main(void)
{
    int series[] = {5, 7, 6, 8, 9, 2, 1, 4, 3};
    int len = sizeof(series) / sizeof(series[0]);

    // 排序前,打印
    printf("排序前,打印\n");
    print_series(series, len);

    // 排序
    shell_sort(series, len);
   
    // 排序后,打印
    printf("排序后,打印\n");
    print_series(series, len);

    return 0;
}

时间复杂度:当n -> 无穷大,\(On(log_2n)^2\)

空间复杂度:\(O(1)\)

特点:

1)记录跳跃式地移动导致排序不稳定
2)只适用顺序结构
3)增量序列gap可以有多种取法,但应该使增量序列中的值没有除1之外的公因子,并且最后一个增量值必须等于1
4)特别适用初始记录无序、n较大时的情况
5)当每轮循环中 gap = gap / 2 修改为 gap = gap - 1 ,算法就成了直接插入排序

参考引用

数据结构第二版:C语言版(严蔚敏)

标签:折半,int,series,插入排序,len,gap,排序
From: https://www.cnblogs.com/caojun97/p/17662219.html

相关文章

  • Oracle查看占用表空间最大的表(排序)
    selectt.owner,t.segment_name,t.tablespace_name,bytes/1024/1024/1024assizes,q.num_rows,t.segment_type fromdba_segmentst leftjoindba_tablesq   ont.segment_name=q.table_name  andt.owner=q.owner wheret.segment_type='TABLE'  andt.tab......
  • 快排及链表排序
    文章目录一、普通的快排二、链表的创建三、链表的冒泡排序四、链表快排五、链表归并排序一、普通的快排voidQuickSort(vector<int>&vec,intlow,inthigh){ intpivot=vec[low];//选择第一个元素作为枢纽元 //mid总是指向最后一个比枢纽元小的位置,当需要交换元素时,先......
  • 快速排序
    快速排序是一种常见的排序算法,它的基本思想是通过分治的策略将一个大问题拆分为若干个小问题,并通过递归求解这些小问题,最终将整个问题排序完成。具体的步骤如下:选择一个基准元素,一般选择第一个元素。将序列中小于等于基准元素的元素移动到基准元素的左边,大于基准元素的元素移......
  • 希尔排序整理
    算法原理代码实现1publicstaticvoidsort(int[]array){2//数据间隔h8>4>2>13inth=array.length/2;4while(h>=1){5for(intstart=0;start<h;start++){6//对start,start+h,......
  • 数组二分查找:35. 搜索插入位置、34. 在排序数组中查找元素的第一个和最后一个位置
    35. 搜索插入位置1classSolution:2defsearchInsert(self,nums:List[int],target:int)->int:3left,right=0,len(nums)-145whileleft<=right:#左闭右闭6mid=left+(right-left)//27ifnum......
  • 【C++STL基础入门】vector运算和遍历、排序、乱序算法
    @TOC前言C++标准库提供了丰富的容器和算法,其中vector是最常用的容器之一。它以动态数组的形式存储元素,并提供了许多方便的运算符和算法来操作和处理数据。本文将介绍vector的基本运算、遍历方法、排序算法以及乱序算法。通过学习这些内容,您将能够更加灵活、高效地使用vector容器。......
  • 冒泡排序
    冒泡排序是一种简单的排序算法,它重复地遍历要排序的列表,比较相邻的元素,并根据需要交换它们的位置,直到整个列表排序完成为止。具体步骤如下:从列表的第一个元素开始,比较它与下一个元素的大小。如果当前元素较大,则交换它与下一个元素的位置。继续向列表的下一个元素进行比较,重复......
  • 插入排序之希尔排序
    1voidshell_sort()2{3unsignedchari=0,j=0,gap;4unsignedchararr[10]={4,1,3,9,6,2,8,5,0,7};5unsignedcharlen=sizeof(arr);6unsignedchartemp;7chark;8gap=len;9while(gap)10{11gap......
  • 插入排序之直接插入排序
    1voidinsert_sort()2{3inti,j;4unsignedchararray[10]={4,1,3,9,6,2,8,5,0,7};5unsignedcharlen=sizeof(array);67/*遍历所有无序序列*/8for(i=1;i<len;i++)9{10unsignedchartemp=array[i];......
  • 简单排序之选择排序
    1voidselect_sort()2{3inti,j,k;4unsignedchararray[10]={4,1,3,9,6,2,8,5,0,7};5unsignedcharlen=sizeof(array);6unsignedchartemp;78for(i=0;i<len-1;i++)9{10k=i;11/*遍历所以有......