嵌入式学习 day25:哈希表及排序与查找

一、哈希表

1.1 什么是哈希表

哈希表是一种根据键(Key) 直接访问数据的数据结构。它通过哈希函数把键映射到一个下标,然后直接在该位置存取数据。

1.2 为什么用哈希表

数据结构 查找元素
数组 O(n)(遍历)
有序数组 O(log n)(二分查找)
链表 O(n)
二叉搜索树 O(log n)
哈希表 O(1)(近乎常数时间)

哈希表的查找速度非常快,和元素数量多少关系不大。

1.3 哈希冲突

不同数据经过哈希函数映射后得到相同的键值,就叫哈希冲突

解决哈希冲突的常用方法

  • 链地址法:每个哈希桶里挂一个链表,冲突的数据放在链表里

  • 开放地址法:如果当前位置被占了,就往后找空位

text

复制代码
链地址法示例:
索引0 → [数据A] → [数据B]  ← A和B冲突了,串成链表
索引1 → [数据C]
索引2 → NULL
索引3 → [数据D] → [数据E] → [数据F]

二、排序算法

2.1 排序算法对比

算法 平均时间复杂度 最坏情况 稳定性 特点
冒泡排序 O(n²) O(n²) 稳定 相邻比较,大数后移
选择排序 O(n²) O(n²) 不稳定 每轮选最小放前面
插入排序 O(n²) O(n²) 稳定 将元素插入有序部分
希尔排序 O(n log n) O(n²) 不稳定 分组+插入排序
快速排序 O(n log n) O(n²) 不稳定 分治,选基准值分组

2.2 冒泡排序

相邻两个元素比较,大的往后移。每轮结束当前最大的数就"沉"到了最后面。

c

复制代码
void BubbleSort(int a[], int len)
{
    for (int i = 0; i < len - 1; i++) {
        for (int j = 0; j < len - 1 - i; j++) {
            if (a[j] > a[j + 1]) {
                int tmp = a[j];
                a[j] = a[j + 1];
                a[j + 1] = tmp;
            }
        }
    }
}

2.3 选择排序

每轮从剩下的元素里找到最小的,放到前面。

c

复制代码
void SelectionSort(int a[], int len)
{
    for (int i = 0; i < len - 1; i++) {
        int min = i;
        for (int j = i + 1; j < len; j++) {
            if (a[j] < a[min]) {
                min = j;
            }
        }
        if (min != i) {
            int tmp = a[i];
            a[i] = a[min];
            a[min] = tmp;
        }
    }
}

2.4 插入排序

把数组分成"已排序"和"未排序"两部分,从未排序部分取元素插入到已排序部分的正确位置。

c

复制代码
void InsertionSort(int a[], int len)
{
    for (int i = 1; i < len; i++) {
        int key = a[i];
        int j = i - 1;
        while (j >= 0 && a[j] > key) {
            a[j + 1] = a[j];
            j--;
        }
        a[j + 1] = key;
    }
}

2.5 希尔排序

插入排序的改进版。先把数据按步长分组,每组分别做插入排序,步长逐步缩小,最后步长为1时做最后一次插入排序。

c

复制代码
void ShellSort(int a[], int len)
{
    for (int gap = len / 2; gap > 0; gap /= 2) {
        for (int i = gap; i < len; i++) {
            int key = a[i];
            int j = i - gap;
            while (j >= 0 && a[j] > key) {
                a[j + gap] = a[j];
                j -= gap;
            }
            a[j + gap] = key;
        }
    }
}

2.6 快速排序

核心思想是分治。选一个基准值,把比它小的放左边、比它大的放右边,然后递归对左右两边做同样的操作。

c

复制代码
int Partition(int a[], int low, int high)
{
    int key = a[low];
    while (low < high) {
        while (low < high && a[high] >= key) high--;
        a[low] = a[high];
        while (low < high && a[low] <= key) low++;
        a[high] = a[low];
    }
    a[low] = key;
    return low;
}

void QuickSort(int a[], int low, int high)
{
    if (low < high) {
        int mid = Partition(a, low, high);
        QuickSort(a, low, mid - 1);
        QuickSort(a, mid + 1, high);
    }
}

三、今日总结

今天学了哈希表排序算法,核心要点如下:

哈希表

  1. 通过哈希函数把键映射到存储位置

  2. 查找时间复杂度接近 O(1)

  3. 哈希冲突用链地址法或开放地址法解决

排序算法

  1. 冒泡排序:相邻比较,大数后移 → O(n²),稳定

  2. 选择排序:每轮选最小放前面 → O(n²),不稳定

  3. 插入排序:元素插入有序部分 → O(n²),稳定

  4. 希尔排序:分组插入排序 → O(n log n),不稳定

  5. 快速排序:分治,选基准值分组 → O(n log n),不稳定

今日感悟

哈希表用空间换时间,多占点内存,换来接近瞬时的查找速度。

不同场景适用不同的算法,数据量小、要求稳定,用插入排序;数据量大、追求速度,用快速排序。

相关推荐
yiqiefeimeng2 小时前
C语言指针难倒90%人?买房比喻让你瞬间开窍
c语言·学习·编程·指针·比喻
GHL2842710902 小时前
Skill学习
学习·ai
田径他爸来了2 小时前
嵌入式学习第30天——软中断,Ip进程间的通信
学习
奇树谦2 小时前
HDD 为什么适合顺序大文件读写:从 RAID 5 到 RAID 50 的原理与性能分析
linux·运维·网络
caimouse2 小时前
ReactOS 窗口系统分析(5):可见区域与窗口 DC — vis.c + windc.c
c语言·开发语言
hi_ro_a3 小时前
Linux基础开发工具详解
linux·运维·服务器
嵌入式阿蔡3 小时前
Linux_01:交叉编译与开发环境实战——从单片机跨到 Linux 的第一道坎
linux·运维·网络·单片机·嵌入式硬件·嵌入式实时数据库
Pocker_Spades_A3 小时前
终端里也能斗地主:Linux部署Ratel,从本地对战到公网联机
linux·运维·服务器
佳児素花痴╮4 小时前
C语言链接库
linux·运维·服务器