上一节我们说到我们己经实现了一般Vector可以做到的自动扩充,告诉随机存取,那么现在我们需要完成vector的一个排序的功能。

排序算法我们网上一百度哇~~!很常见的就有8大排序算法;

1.选择排序  2.冒泡排序  3.插入排序  4.快速排序

5.归并排序  6.桶排序  7.堆排序  8.希尔排序

具体的思想本猿就不展开讲啦,现在C语言应用的场景大多数在服务器和嵌入式设备,服务器数据量大,嵌入式设备资源有限

两者是对时间复杂度和空间负责度的两个极端。

一开始我想要优化堆排序,使得堆排序的空间复杂度减小;

优化的思想很简单;我们并不申请一个与原数组大小一致的空间,而是申请一个他的映射数组;

当我们堆排序 insert 和 delete 后,映射数组中就存储了有序数据的信息;

例如:映射数组mapTab[0] = 20; //也就意味着真正有序数组的第0位是现在数组的第20位;将第20位移动至第0位;在有序数组的第20位

现在在哪一个位置;依次跳转映射,将整个映射表遍历后,数组就变成有序的啦;

以下是实现代码:

/*
*
* 此函数为堆排序的改进版本,使用了一个数组作为数据的映射,使用此数组记住当前位置正确的数据下标是多少;
* 例如 数组a[0] = 12;即表示 在真正有序的数据中第 [0] 位应该是现在的第12位数据;但是在这里为了节约空间,
* 将数据的顺序颠倒;也就是说 a[maxsize] 中存放的数字下标就是有序数据的第[0]位;
*
* insert delete后,生成的数组就是我们的映射表,这个是依照迭代的思想,从第0位开始,找出第0位应该存放的数据是第n位,
* 迭代,需要应该在第n位的数据现在在第y位。依次寻找迭代;
* 由此一定会迭代出一个循环,此时将之前缓存起来的第0位数据放入它应该去的位置,同时,自增,查看第1位,如果第1位已经就绪则继续自增
* 性能分析;
* 此方法相对于堆排序,将空间缩减为每个元素只占用5个字节,如果元素类型大小小于5,则使用此方法将浪费空间和时间,
*/
void heapSortInt(VCT_DOU_t *v)
{
u32 *mapTab = (u32 *)malloc(sizeof(u32) * (v->size + ));
// u32 temp[50] = {0};
u32 index = ;
// insert min
for (u32 i = ; i <= v->size; i++)
{
index = i;
for (; index > && v->compare(&v->data[i - ], &v->data[mapTab[(index >> )]]); index >>= )
mapTab[index] = mapTab[index >> ];
mapTab[index] = i - ;
}
// delete min
u32 child = ;
u32 minindex;
for (u32 i = ; i < v->size; i++)
{
minindex = mapTab[];
mapTab[] = mapTab[v->size - i];
index = ;
for (; (index << ) <= (v->size - i - ); index = child)
{
child = (index << );
if (child != (v->size - i - ) && compare(&v->data[mapTab[child + ]], &v->data[mapTab[child]]))
{
child++;
}
if (compare(&v->data[mapTab[child]], &v->data[mapTab[v->size - i]]))
mapTab[index] = mapTab[child];
else
break;
}
mapTab[index] = mapTab[v->size - i];
mapTab[v->size - i] = minindex;
} // double t;
u8 *sta = (u8 *)malloc(sizeof(u8) * v->size);
// u8 sta[50] = {0};
template_t t = {};
memset(sta, , sizeof(u8) * v->size);
for (u32 i = v->size; i > ; i--)
{
printf("\n[%d] %d", i, mapTab[i]);
if (sta[v->size - i] == )
continue;
t = v->data[v->size - i];
u32 start = v->size - i;
u32 next = mapTab[i];
while (next != (v->size - i))
{
v->data[start] = v->data[next];
sta[start] = ;
start = next;
next = mapTab[v->size - next];
}
v->data[start] = t;
sta[start] = ;
}
v->show(v);
}

经过本猿的测试发现,时间消耗是普通堆排序的5倍时间(数组大小10000000);虽然时间复杂度依旧是nlogn,但是我还是不能接受,奈何自己实在没有想到更好的优化方法;

不得已,只能转变策略;

我个人而言对快读排序不太放心,虽然它被广泛使用,但是其性能是不稳定的,而堆排序就很稳定,因此我在头文件中定义了一个宏。如果这个宏有配置使用快排或者堆排序,那么

就使用快排或者堆排序,否则就使用冒泡排序;

现已将代码上传至github:https://github.com/KimAlittleStar/cstd

目录

1.引言

2.1 C语言_实现简单基础的vector

2.2 C语言_实现数据容器vector(排序功能)

3.1 C语言_实现AVL平衡二叉树

3.2 C语言_实现数据容器set(基础版)

4 C语言_实现简单基础的map

2.2 C语言_实现数据容器vector(排序功能)的更多相关文章

  1. JavaScript 字符串与数组互转,并保持数据去重、排序功能

    var valueArr = new Array(); if( $("input[name='type']").val() != ""){ valueArr = ...

  2. 3.1 C语言_实现AVL平衡二叉树

    [序] 上节我们实现了数据结构中最简单的Vector,那么来到第三章,我们需要实现一个Set set的特点是 内部有序且有唯一元素值:同时各种操作的期望操作时间复杂度在O(n·logn): 那么标准的 ...

  3. C++关联式容器的排序准则

    stl中set和map为关联式容器,会根据排序准将元素自动排序.原型如下: template<class _Kty, class _Pr = less<_Kty>, class _A ...

  4. R语言 我要如何开始R语言_数据分析师

    R语言 我要如何开始R语言_数据分析师 我要如何开始R语言? 很多时候,我们的老板跟我们说,这个东西你用R语言去算吧,Oh,My god!什么是R语言?我要怎么开始呢? 其实回答这个问题很简单,首先, ...

  5. DataSet的灵活,实体类的方便,DTO的效率:SOD框架的数据容器,打造最适合DDD的ORM框架

    引言:DDD的困惑 最近,我看到园子里面有位朋友的一篇博客 <领域驱动设计系列(一):为何要领域驱动设计? >文章中有下面一段话,对DDD使用产生的疑问: •没有正确的使用ORM, 导致数 ...

  6. SOD框架的数据容器,打造最适合DDD的ORM框架

    SOD框架的数据容器,打造最适合DDD的ORM框架 引言:DDD的困惑 最近,我看到园子里面有位朋友的一篇博客 <领域驱动设计系列(一):为何要领域驱动设计? >文章中有下面一段话,对DD ...

  7. sql 两大类 DDL数据定义语言 和DCL数据控制语言

    SQL分为五大类: DDL:数据定义语言   DCL:数据控制语言     DML:数据的操纵语言  DTL:数据事务语言  DQL:数据查询语言. DDL (date definition lang ...

  8. Netty 中的内存分配浅析-数据容器

    本篇接续前一篇继续讲 Netty 中的内存分配.上一篇 先简单做一下回顾: Netty 为了更高效的管理内存,自己实现了一套内存管理的逻辑,借鉴 jemalloc 的思想实现了一套池化内存管理的思路: ...

  9. 零基础学Python:数据容器

    1.常用操作 列表常用操作 在 ipython 中定义一个 列表,例如: l= list() 输入 l. 按下 TAB 键, ipython 会提示 字典 能够使用的函数如下: 可以到官方网址查询使用 ...

随机推荐

  1. 第一次接触WebSocket遇到的坑以及感受

    要求用.net写一个服务,然后通过webscoket实现客户端与服务端之间的通信. 第一次知道.net还可以用来写服务,然后问题来了,服务是什么- -..下面图里的就是服务,可以停止暂停和启动. 我要 ...

  2. Linux初识之VMWare14中配置Centos7桥接网络环境

    1.查看当前初始环境如下:

  3. 【linux】【ELK】搭建Elasticsearch+Logstash+Kibana+Filebeat日志收集系统

    前言 ELK是Elasticsearch.Logstash.Kibana的简称,这三者是核心套件,但并非全部. Elasticsearch是实时全文搜索和分析引擎,提供搜集.分析.存储数据三大功能:是 ...

  4. 使用JSP+Servlet+Jdbc+Echatrs实现对豆瓣电影Top250的展示

    使用JSP+Servlet+Jdbc+Echatrs实现对豆瓣电影Top250的展示 写在前面: 有的小伙伴,会吐槽啦,你这个标题有点长的啊.哈哈 ,好像是的!不过,这个也是本次案例中使用到的关键技术 ...

  5. Maven 梳理-自动创建Maven项目(非web)

    mvn archetype:create和mvn archetype:generate create is deprecated in maven 3.0.5 and beyond,在maven3.0 ...

  6. 使用Java元注解和反射实现简单MVC框架

    Springmvc的核心是DispatcherServlet来进行各种请求的拦截,进而进行后续的各种转发处理.流程图如下: 说明:客户端发出一个http请求给web服务器,web服务器对http请求进 ...

  7. SpringBootSecurity学习(13)前后端分离版之JWT

    JWT 使用 前面简单介绍了把默认的页面登录改为前后端分离的接口异步登录的方法,可以帮我们实现基本的前后端分离登录功能.但是这种基本的登录和前面的页面登录还有一个一样的地方,就是使用session和c ...

  8. 3D漫游的分类 3D Navigation Taxonomy

    在2001年CHI发表的论文中1,Tan等人提出了一种对3D漫游的分类方法. 当时关于3D漫游(3D Navigation)的研究主要分为两种:一种是发掘有关漫游的认知原则,一种是开发一些具体的漫游技 ...

  9. 主动降噪技术(ANC)的前生今世–行业分析

    一 原始玩家 1978年,创始人Amar G. Bose博士在从欧洲飞往波士顿的飞机上,发现飞机引擎的噪音扫净了他戴耳机欣赏音乐的兴致.这激发了他在BOSE公司进行一项消噪科技的研究.弹指之间,十年过 ...

  10. 并发编程的模型分类(转载于https://link.zhihu.com/?target=http%3A//www.54tianzhisheng.cn/2018/02/28/Java-Memory-Model/)强烈推荐!

    在并发编程需要处理的两个关键问题是:线程之间如何通信 和 线程之间如何同步. 通信 通信 是指线程之间以何种机制来交换信息.在命令式编程中,线程之间的通信机制有两种:共享内存 和 消息传递. 在共享内 ...