C语言离散化
C语言离散化
最近看到STL就不想用, 于是写个C语言离散化, 居然能过主席树板子, 就写个博客介绍一下.
qsort
和bsearch
都在<stdlib.h>
或<cstdlib>
里.
什么是离散化
一种映射, 可以把值域从 \([1, Val_{\max}]\) 变成 \([1, N]\) 且保留大小关系, 多用于值域线段树和各种需要从值域考虑的数据结构.
如何离散化
1. 排序
可以用C语言的排序函数void qsort(void *bg, int len, int sz, int *cmp(const void *, const void *))
.
先讲一下qsort
.
bg
为开始地址, 比如数组 \(a\) 从 \(1\) 开始就是 \(a + 1\) .len
为数组长度, 一般用 \(N\) .sz
为元素大小, 直接sizeof(type)
简单粗暴, 如sizeof(long long)
.cmp
为比较函数, 传入两个void*
类型的地址需要转换成原类型, 以下称第一个参数强转后访问到的值为\(x\)第二个为 \(y\), \(x < y\) 时返回负数, \(x = y\) 返回 \(0\), \(x > y\) 时返回正数, 比如排序字符串可以直接用strcmp
, 排序整数则可以直接返回 \(x - y\).
那么很显然, 排序的代码就写出来了.
int cmp(const void *x, const void *y) // 比较 {return *(int*)(x) - *(int*)(y);} void lsh() { // 离散化 // b 是离散化用的辅助数组, 已经在输入时就是 a 的复制了 // S 是输入的长度 qsort(b + 1, S, sizeof(int), cmp); /* 有一种逆天的写法, 感兴趣的同学可以探索一下匿名函数, 仅限C++11以上 qsort(b + 1, S, sizeof(int), [](const void *x, const void *y){return *(int*)(x) - *(int*)(y);}); */ // 待续写 }
2. 降重
这里我们使用在原数组直接降重, 类似
if (a[i] ^ a[i - 1]) // 如果 a[i] 不等于 a[i - 1] stk[++tp] = a[i] // 在栈顶加入 a[i]
所以很容易写出去重代码.
int cmp(const void *x, const void *y) {return *(int*)(x) - *(int*)(y);} void lsh() { qsort(b + 1, S, sizeof(int), cmp); N = 1; // N 是离散化后的值域大小 lim (i, 2, S, 1) // for (int i(2); i <= S; i += 1) if (b[i] ^ b[i - 1]) // 如果这个元素没有重复 b[++N] = b[i]; // 放在上一个不重复的后面 // 待续写 }
二分查找在离散化后的值域中的大小
二分查找可以用C语言的void* bsearch(void *val, void *bg, int len, int sz, int cmp(const void *, const void *))
.
bsearch
和qsort
基本一样, 这里只讲一下不一样的地方.
val
是要找的值的地址.- 返回的是
void*
类型的地址, 需要强转再使用.
那么也可以写出最后完成的代码.
int cmp(const void *x, const void *y) {return *(int*)(x) - *(int*)(y);} void lsh() { qsort(b + 1, S, sizeof(int), cmp); N = 1; lim (i, 2, S, 1) if (b[i] ^ b[i - 1]) b[++N] = b[i]; lim (i, 1, S, 1) // 原数组 a 的每个元素的离散化值都要找 // 二分查找后强转然后减去头地址 (b + 1) 后加 1 避免 0 // 稍微优化一下 - (b + 1) + 1 就是 - b a[i] = (int*)bsearch(a + i, b + 1, N, sizeof(int), cmp) - b; }
原文来自CnBlogs, 作者: 指针神教教主Defad.
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10亿数据,如何做迁移?
· 推荐几款开源且免费的 .NET MAUI 组件库
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· c# 半导体/led行业 晶圆片WaferMap实现 map图实现入门篇
· 易语言 —— 开山篇