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

上一节我们说到我们己经实现了一般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 + 1));
    //    u32 temp[50] = {0};
    u32 index = 0;
    // insert min
    for (u32 i = 1; i <= v->size; i++)
    {
        index = i;
        for (; index > 1 && v->compare(&v->data[i - 1], &v->data[mapTab[(index >> 1)]]); index >>= 1)
            mapTab[index] = mapTab[index >> 1];
        mapTab[index] = i - 1;
    }
    // delete min
    u32 child = 0;
    u32 minindex;
    for (u32 i = 0; i < v->size; i++)
    {
        minindex = mapTab[1];
        mapTab[1] = mapTab[v->size - i];
        index = 1;
        for (; (index << 1) <= (v->size - i - 1); index = child)
        {
            child = (index << 1);
            if (child != (v->size - i - 1) && compare(&v->data[mapTab[child + 1]], &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 = {0};
    memset(sta, 0, sizeof(u8) * v->size);
    for (u32 i = v->size; i > 0; i--)
    {
        printf("\n[%d]  %d", i, mapTab[i]);
        if (sta[v->size - i] == 1)
            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] = 1;
            start = next;
            next = mapTab[v->size - next];
        }
        v->data[start] = t;
        sta[start] = 1;
    }
    v->show(v);
}

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

不得已,只能转变策略;

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

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

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

目录

1.引言

2.1实现简单基础的vector

2.2实现排序功能的vector

原文地址:https://www.cnblogs.com/kimalittlestar/p/11716252.html

时间: 2024-10-10 18:30:39

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

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

var valueArr = new Array(); if( $("input[name='type']").val() != ""){ valueArr = $("input[name='type']").val().split(","); } if(selectedValue != "" && $.inArray(selectedValue, valueArr) == -1){ val

iOS_18_控制器切换_NavigationController_push方式_传递数据

最终效果图: storyboard示意图: BeyondViewController.h // // BeyondViewController.h // 18_控制器切换_navigation_push_通过storyboard方式 // // Created by beyond on 14-7-31. // Copyright (c) 2014年 com.beyond. All rights reserved. // #import <UIKit/UIKit.h> @interface Be

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

引言:DDD的困惑 最近,我看到园子里面有位朋友的一篇博客 <领域驱动设计系列(一):为何要领域驱动设计? >文章中有下面一段话,对DDD使用产生的疑问: •没有正确的使用ORM, 导致数据加载过多,导致系统性能很差. •为了解决性能问题,就不加载一些导航属性,但是却把DB Entity返回上层,这样对象的一些属性为空,上层使用这个数据时根本不知道什么时间这个属性是有值的,这个是很丑陋的是不是? 博主说的第一个问题,是因为使用ORM的人把实体类的全部属性的数据查询出来了,相当于执行了 sele

现代C语言程序设计之数据存储(一)

现代C语言程序设计之数据存储(一) C语言 2.1 计算机信息存储 2.1.1 计算机常用存储单位 在计算机最底层,数据都是以二进制(01010)的补码方式存储,而计算机中最小的存储单位是位(bit),用来表示0或者1. 计算机中最基本的存储单位是字节(Byte),1个字节对应8个位(Bit). 而日常应用中常使用的基本存储单位包括KB,MB,GB,TB.它们之间都是以1024换算的,如下所示 1TB=1024GB 1GB=1024MB 1MB=1024KB 1KB=1024B 1B=8bit

Android技术10:Java与C语言之间简单数据的传递

由于C语言和Java语言之间很多类型不一致性,因此使用native时,需要数据类型转换.下面演示分别传递整型,字符串,整型数组,Java静态方法传递数据. 1.创建native方法 我们单独创建一个NativeClass类来存放native方法 1 package com.forsta.ndk; 2 3 public class NativeClass { 4 public native int add(int x,int y); 5 public native String showStrin

R语言XML格式数据导入与处理

数据解析 XML是一种可扩展标记语言,它被设计用来传输和存储数据.XML是各种应用程序之间进行数据传输的最常用的工具.它与Access,Oracle和SQL Server等数据库不同,数据库提供了更强有力的数据存储和分析能力,例如:数据索引.排序.查找.相关一致性等,它仅仅是存储数据.事实上它与其他数据表现形式最大的不同是:它极其简单,这是一个看上去有点琐细的优点,但正是这点使它与众不同. 针对XML格式数据,R语言XML包可以对其进行数据导入与处理,详见下面的案例说明. 案例1 直接输入一段标

C语言之查看数据在内存中表现形式

#include<stdio.h> void viewRAM(); void main() { viewRAM(); } //查看内存,打印内存地址 void viewRAM() { int b[5] = { 1, 2, 3, 4, 5 }; //打印内存地址 printf("%x", b); //注意:数组在内存中连续排列的 system("pause"); } 1,在打印内存地址代码后面,右键. 2,选择断点,插入断点. 3,这时断点已经生效. 4,

C语言判断系统数据大/小端存储方式

小端存储:数据的低位部分,存储于存储器的低地址空间里. 大端存储:数据的低位部分,存储于存储器的高地址空间里. 首先,一般PC数据存储方式是小端存储. 基本实现思想是:将存储器中所存的数据按字节以地址顺序输出,与存入数据的高低位进行比较,即得出结论. 实现方法一: 1 #include <stdio.h> 2 int main(void) 3 { 4 short int x; 5 char *arr; 6 7 x = 0x1122; 8 arr = (char *)&x; 9 10 i

2、C语言——C语言组成与数据

C语言组成与数据 组成结构: 组成:若干文件 文件:若干函数 函数:函数头+函数尾 函数头:四部分->函数名+() 函数体:{}+语句 语句:三类语句 类型1->/* */ 类型2->定义语句: 类型3->执行语句: 数据与数据类型 数据四类:常量 变量 表达式 函数与预编译 常量:值不发生变化的量 变量:值随时随地改变的量 表达式:用运算符将数据连接起来的合法式子 函数:调用具有一定功能的函数作为运算量 数据类型四大类:基本类型.构造类型.指针类型.空类型 基本类型:整形int