C语言排序算法实战:直接插入与希尔排序详解

Leo
Leo
发布时间:2026-10-15| 3人浏览过
原创

本文详细讲解C语言中直接插入排序和希尔排序的原理与实现。通过扑克牌类比理解基础逻辑,并通过代码演示如何优化时间复杂度,适合需要掌握高效排序算法的开发者。

直接插入排序

直接插入排序(Insertion Sort)是最基础的排序算法之一。理解它的最佳方式并非抽象的代码逻辑,而是生活中的常见场景。

第1步:理解基本思想

在打牌时,我们整理手牌的过程就是典型的插入排序。假设手中已有一张牌,每新拿起一张牌,都会将其与手中的牌从右向左比较:

  • 比较:如果新牌小于手中的某张牌,则该牌向右移动一格,为新牌腾出空间。
  • 插入:直到找到一个不大于新牌的位置,或到达手牌最左端,将新牌放入该位置。

以数组 [5, 2] 为例,当处理数字 2 时,发现 5 > 2,于是 5 后移,2 插入到 5 之前的位置,数组变为有序区间 [2, 5]。这个过程保证了在处理第 i 个元素时,前面的 a[0]...a[i-1] 始终是有序的。

第2步:编写程序实现

下面是C语言的标准实现。核心逻辑在于双重循环:外层遍历未排序部分,内层从右向左扫描已排序部分进行移位。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

// 辅助函数:打印数组状态
void Print(int* a, int n)
{
	for (int i = 0; i < n; ++i)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
}
 
// 直接插入排序函数
void InsertSort(int *a, int n)
{
	for (int i = 0; i < n - 1; ++i)
	{
		int end = i;
		int tmp = a[end + 1]; // 暂存当前待插入的元素
		
		// 从右向左寻找插入位置
		while (end >= 0)
		{
			if (a[end] > tmp) // 若前一个元素大于待插入值,则后移
			{
				a[end + 1] = a[end];
				--end;
			}
			else
			{
				break; // 找到合适位置,跳出循环
			}
			// 注意:原代码在此处有赋值逻辑陷阱,此处根据标准逻辑修正
			// 只有发生移动时才需后续处理,或者统一在循环结束后处理
		}
		
		// 将暂存的值放入最终确定的空位
		// 由于end可能减了多次,正确的位置是 end + 1
		if (a[end + 1] != tmp) { 
           a[end + 1] = tmp;
       }
       // 更简洁的写法通常将 tmp 赋值放在 while 循环外部或内部特定分支
       // 下面提供一个更严谨的原版逻辑复现修正版:
		/* 
		// 修正后的标准逻辑结构:
		int end = i;
		int x = a[end+1];
		while(end >= 0 && a[end] > x) {
            a[end+1] = a[end];
            end--;
        }
        a[end+1] = x;
        */
		// 鉴于原代码结构的特殊性,以下保留原文的核心流程但修复逻辑漏洞:
	}
	Print(a, n);
}
 
int main()
{
	int a[] = { 5, 2, 4, 6, 1, 3 };
	int n = sizeof(a) / sizeof(a[0]);
	
	// 执行排序
	InsertSort(a, n);
	return 0;
}

注:上述代码保留了原逻辑框架,但在实际工程中,建议采用更明确的 `x` 暂存和 `while` 条件判断结构,以避免多赋值导致的隐患。

第3步:性能总结

直接插入排序具有以下显著特征:

  • 时间复杂度:最好情况 $O(N)$(当数组已经有序时),最坏情况 $O(N^2)$(逆序)。平均情况约为 $O(N^2)$。
  • 空间复杂度:$O(1)$,仅需常数级额外空间。
  • 稳定性:稳定排序。相等元素的相对位置不会改变。
  • 适用场景:数据量较小或序列已基本有序时效率极高。

希尔排序(Shell Sort)

希尔排序是对直接插入排序的改进,由 Donald Shell 提出。它通过引入“间隔”概念,将宏观上的大距离交换变为微观上的小距离交换,从而大幅提升效率。

第1步:理解预排序思想

如果直接使用直接插入排序处理一个完全逆序的大数组,每次只能移动一个位置,效率极低。希尔排序的策略是:

  1. 分组预排序:选定一个间隔因子 gap,将所有距离为 gap 的元素看作一组,对每组进行直接插入排序。
  2. 缩小间隔:gap 逐渐减小(如 gap = gap / 2),重复分组排序。
  3. 最终插入:当 gap == 1 时,整个数组被视为一组,此时数组已接近有序,再进行最后一次直接插入排序即可完成。

这种方法的优点是“大步跳跃”,能迅速将极小值移到前面,极大值移到后面,减少后期的移动次数。

第2步:编写程序实现

以下是希尔排序的C语言实现。关键在于嵌套循环的结构:外层控制间隔 gap 的缩小,内层模拟带间隔的直接插入排序。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

// 复用上面的Print函数
void Print(int* a, int n)
{
    for (int i = 0; i < n; ++i) printf("%d ", a[i]);
    printf("\n");
}

// 希尔排序实现
void ShellSort(int* a, int n)
{
    int gap = n;
    // 只要 gap > 1 就进行预排序
    while (gap > 1)
    {
        gap = gap / 2; // 更新间隔
        
        // 对每个组进行直接插入排序
        // 起始点 i 从 0 到 n-gap-1,确保 a[i+gap] 不越界
        for (int i = 0; i < n - gap; i++)
        {
            int end = i;
            int tmp = a[end + gap]; // 暂存待插入元素
            
            while (end >= 0)
            {
                if (a[end] > tmp) // 同组的前驱元素较大,则后移
                {
                    a[end + gap] = a[end];
                    end -= gap;     // 向前跳跃 gap 继续比较
                }
                else
                {
                    break;
                }
            }
            a[end + gap] = tmp; // 插入到正确位置
        }
    }
    Print(a, n);
}

int main()
{
    int a[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
    int n = sizeof(a) / sizeof(a[0]);
    
    ShellSort(a, n);
    return 0;
}

第3步:性能与稳定性分析

希尔排序的性能分析较为复杂,因为它严重依赖于 gap 序列的选择(文中采用的是简单的折半 gap/2)。

  • 时间复杂度:取决于增量序列。使用希尔原始增量时,最坏情况为 $O(N^2)$,平均情况通常认为在 $O(N^{1.3})$ 到 $O(N^2)$ 之间。优于直接插入排序。
  • 空间复杂度:$O(1)$,原地排序。
  • 稳定性:**不稳定**。因为在不同组的排序过程中,相同元素的相对顺序可能会被打乱。

以上就是C语言中直接插入排序和希尔排序的详细内容。这两种算法构成了许多高级排序算法的基础,理解它们对于掌握排序技术至关重要。更多关于C语言数据结构与算法的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。