说明
  本文章旨在总结备份、方便以后查询,由于是个人总结,如有不对,欢迎指正;另外,内容大部分来自网络、书籍、和各类手册,如若侵权请告知,马上删帖致歉。
  QQ 群 号:513683159 【相互学习】
内容来源
  《系统程序员成长计划》、C语言实现动态数组,克服静态数组大小固定的缺陷

上一篇:读书笔记 ——《系统程序员成长计划》篇6:写的又快又好的秘诀
下一篇:读书笔记 ——《系统程序员成长计划》篇8:排序算法

目录:

  • 一、概念
    • 1、什么是动态数组?
    • 2、双向链表和动态数组的对比
  • 二、动态数据的实现
    • 1、简单实现
    • 2、书中示例 关键函数简述
      • (1)动态数组 结构体
      • (2)动态数组 创建函数
      • (3)动态数组 扩展函数
      • (4)动态数组 减小函数
      • (5)动态数组 插入函数(包含头插法与尾插法)
      • (6)动态数组 删除函数
      • (7)动态数组 销毁函数
    • 3.书中程序
      • typedef.h
      • darray.h
      • darray.c
      • Makefile

一、概念

1、什么是动态数组?

  C语言中,数组长度必须在创建时指定,且只能是常数不能是变量。定义后系统将为它分配固定大小的空间,以后不能改变,称为静态数组。但在编程过程中,有时所需的内存空间无法预先确定,故用静态数组的办法很难解决。
  动态数组可随程序需要而重新指定大小。通过执行代码在内存空间从堆(heap)上分配(即动态分配)的。当程序执行到这些语句时,才为其分配。程序员自己负责释放内存。

2、双向链表和动态数组的对比

情形 动态数组 双向链表
空间占用情况 占用一块连续的内存 每个结点占用一块内存
频繁增删数据 需移动后面元素 只需修改前后元素指针,但容易造成内存碎片
是否支持多种高效排序算法 支持,如:快速排序、归并排序,堆排序等 表现不好,甚至不如冒泡排序
排序好的数据 可使用二分查找 仍只能用顺序查找
小量数据 区别不大 区别不大

二、动态数据的实现

  同样选择存指针,故实现的是指针数组。

1、简单实现

#include <stdio.h>
#include <stdlib.h>
int main(){int arrLen;  // 数组长度int *array;  // 数组指针int i;  // 数组下标printf("输入数组长度:");scanf("%d", &arrLen);// 动态分配内存空间,如果失败就退出程序array = (int*)malloc( arrLen*sizeof(int) );if(!array){printf("创建数组失败!\n");exit(1); }// 向内存中写入数据for(i=0; i<arrLen; i++){array[i] = i+1;} // 循环输出数组元素for(i=0; i<arrLen; i++){printf("%d  ", array[i]);}printf("\n");free(array);  return 0;
}

实现现象:

输入数组长度:20
1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20

  这边定义了数组指针,指向malloc函数创建的一整块内存空间,实现动态数组,动态输入数组长度后自动赋值数据并输出。实际上与静态数组并没有什么区别。

2、书中示例 关键函数简述

(1)动态数组 结构体

struct _DArray;
typedef struct _DArray DArray;
typedef void     (*DataDestroyFunc)(void* ctx, void* data);struct _DArray
{void** data;                                       //数据size_t size;                                        //实际使用大小size_t alloc_size;                                  //分配空间大小void* data_destroy_ctx;                             //销毁函数中上下文数据DataDestroyFunc data_destroy;                       //函数指针,为指向销毁函数
};

(2)动态数组 创建函数

/*** @function:动态数组 创建函数* * @param data_destroy: 使用者编写的销毁函数的函数指针* @param ctx:             销毁函数中的上下文数据* * @return:                指向该动态数组地址* @description:*      开辟一块动态数组结构体大小的空间,并赋初始值。
*/
DArray* darray_create(DataDestroyFunc data_destroy, void* ctx)
{DArray* thiz = malloc(sizeof(DArray));                        //分配空间if(thiz != NULL)                                         //若成功分配则对结构体变量初始化{thiz->data  = NULL;thiz->size  = 0;thiz->alloc_size = 0;thiz->data_destroy = data_destroy;thiz->data_destroy_ctx = ctx;}return thiz;
}

(3)动态数组 扩展函数

/*** @function:动态数组 扩展函数* * @param thiz:           指向动态数组* @param need:           所需动态数组大小* * @return:               运行状态* @description:*   扩展数组时,并不是一次扩展一个元素,而是多个元素,1.5倍为作者的经验所得
*/
#define MIN_PRE_ALLOCATE_NR 10
static Ret darray_expand(DArray* thiz, size_t need)
{return_val_if_fail(thiz != NULL, RET_INVALID_PARAMS);         //若不存在则直接返回错误if((thiz->size + need) > thiz->alloc_size)                   //若现用大小+所需大小 > 现有实际大小{size_t alloc_size = thiz->alloc_size + (thiz->alloc_size>>1) + MIN_PRE_ALLOCATE_NR;//扩大为原来的1.5倍并加上常数void** data = (void**)realloc(thiz->data, sizeof(void*) * alloc_size);             //重新分配大小if(data != NULL){thiz->data = data;thiz->alloc_size = alloc_size;}}return ((thiz->size + need) <= thiz->alloc_size) ? RET_OK : RET_FAIL;                    //判断是否执行成功
}

①函数简介
  realloc()函数:尝试重新调整之前调用 malloccalloc 所分配的ptr所指向的内存块的大小
  函数原型void *realloc(void *ptr, size_t size)
  参数
    1️⃣ ptr – 指针指向一个要重新分配内存的内存块,该内存块之前是通过调用 malloccallocrealloc 进行分配内存的。如果为空指针,则会分配一个新的内存块,且函数返回一个指向它的指针。
    2️⃣ size – 内存块的新的大小,以字节为单位。如果大小为 0,且 ptr 指向一个已存在的内存块,则 ptr 所指向的内存块会被释放,并返回一个空指针。
  返回值
    该函数返回一个指针 ,指向重新分配大小的内存。如果请求失败,则返回 NULL。

②扩展1.5倍的公式size_t alloc_size = thiz->alloc_size + (thiz->alloc_size>>1) + MIN_PRE_ALLOCATE_NR;
  为什么要用这个公式呢
    大多数嵌入式平台并不支持硬件浮点数计算,浮点数的计算要比定点数计算要慢,故并不是直接使用1.5*thiz->alloc_size.又由于若编译器不做优化,则除法操作也较慢,故也不使用thiz->alloc_size+thiz->alloc_size/2.
    而size_t alloc_size = thiz->alloc_size + (thiz->alloc_size>>1)则是最快的方法。后面加上MIN_PRE_ALLOCATE_NR是为避免当thiz->alloc_size为0时存在的错误。

(4)动态数组 减小函数

/*** @function:动态数组  减小空间函数* * @param thiz:        指向动态数组* @return:               运行状态* @description:* 当  实际空间大小的一半 还大于当前数组大小 且 实际空间大小 要大于 固定值 (预防为0的情况)时,减小为有效空间的1.5倍。* 注:删除元素时也并不是马上释放空间,而是等空闲空间高于某个值才释放它们。
*/
static Ret darray_shrink(DArray* thiz)
{return_val_if_fail(thiz != NULL, RET_INVALID_PARAMS);     //若不存在则直接返回错误if((thiz->size < (thiz->alloc_size >> 1)) && (thiz->alloc_size > MIN_PRE_ALLOCATE_NR))//若现有大小 < 已分配1/2倍 且 已分配空间>最小空间{size_t alloc_size = thiz->size + (thiz->size >> 1);                                //将空间大小缩小为现有的1.5倍void** data = (void**)realloc(thiz->data, sizeof(void*) * alloc_size);if(data != NULL){thiz->data = data;thiz->alloc_size = alloc_size;}}return RET_OK;
}

(5)动态数组 插入函数(包含头插法与尾插法)

/*** @function:动态数组 插入函数* * @param thiz:       指向动态数组* @param index:  插入的位置* @param data:        插入的数据* * @return:          运行状态* @description:
*/
Ret darray_insert(DArray* thiz, size_t index, void* data)
{Ret ret = RET_OOM;                                            //定义返回状态初始值为OOMsize_t cursor = index;                                      //形参:数组下标或称游标(插入的位置)return_val_if_fail(thiz != NULL, RET_INVALID_PARAMS);         //若对象为空,则报错为无效参数cursor = cursor < thiz->size ? cursor : thiz->size;            //确认插入元素的位置if(darray_expand(thiz, 1) == RET_OK)                       //若成功扩展空间,则将游标以后位置数据后移一个单位后,将指定位置赋值且数组长度变量+1{size_t i = 0;for(i = thiz->size; i > cursor; i--){thiz->data[i] = thiz->data[i-1];}thiz->data[cursor] = data;thiz->size++;ret = RET_OK;}return ret;
}/*** @function:   头插法* * @param thiz:        指向动态数组* @param data:       插入的数据* * @return:          运行状态* @description:
*/
Ret darray_prepend(DArray* thiz, void* data)
{return darray_insert(thiz, 0, data);
}/**        * @function:   尾插法* * @param thiz:        指向动态数组* @param data:       插入的数据* * @return:          运行状态* @description:
*/
Ret darray_append(DArray* thiz, void* data)
{return darray_insert(thiz, -1, data);
}

(6)动态数组 删除函数

/*** @function: 动态数组 删除数据* * @param thiz:      指向动态数组* @param data:       数据* * @return:     无* @description:*  销毁函数在创建时有使用者进行编写
*/
static void darray_destroy_data(DArray* thiz, void* data)
{if(thiz->data_destroy != NULL){thiz->data_destroy(thiz->data_destroy_ctx, data);}return;
}/*** @function:动态数组 删除函数* * @param thiz:         指向动态数组对象* @param index:        指定下标位置*     * @return:             执行状态* @description:*       删除指定位置数据,数组元素前移。
*/
Ret darray_delete(DArray* thiz, size_t index)
{size_t i = 0;Ret ret = RET_OK;return_val_if_fail(thiz != NULL && thiz->size > index, RET_INVALID_PARAMS);     //若动态数组不存在且删除位置大于数组大小darray_destroy_data(thiz, thiz->data[index]);               //删除指定位置数据for(i = index; (i+1) < thiz->size; i++)                     //将删除后的数组元素前移{thiz->data[i] = thiz->data[i+1];}thiz->size--;darray_shrink(thiz);     //检查是否需要减小空间return RET_OK;
}

(7)动态数组 销毁函数

/*** @function:  动态数组 销毁函数* * @param thiz: 指向动态数组* * @return: 无* @description:*      删除所有数据,销毁动态数组,销毁动态数组空间
*/
void darray_destroy(DArray* thiz)
{size_t i = 0;if(thiz != NULL){for(i = 0; i < thiz->size; i++){darray_destroy_data(thiz, thiz->data[i]);}SAFE_FREE(thiz->data);SAFE_FREE(thiz);}return;
}

3.书中程序

typedef.h

/** File:    typedef.h* Author:  Li XianJing <xianjimli@hotmail.com>* Brief:   common types definition.** Copyright (c) Li XianJing** Licensed under the Academic Free License version 2.1** This program is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License as published by* the Free Software Foundation; either version 2 of the License, or* (at your option) any later version.** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the* GNU General Public License for more details.** You should have received a copy of the GNU General Public License* along with this program; if not, write to the Free Software* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*//** History:* ================================================================* 2008-12-10 Li XianJing <xianjimli@hotmail.com> created.**/#include <stdio.h>
#include <assert.h>
#include <stdlib.h>#ifndef TYPEDEF_H
#define TYPEDEF_Htypedef enum _Ret
{RET_OK,RET_OOM,RET_STOP,RET_INVALID_PARAMS,RET_FAIL
}Ret;typedef void     (*DataDestroyFunc)(void* ctx, void* data);
typedef int      (*DataCompareFunc)(void* ctx, void* data);
typedef Ret      (*DataVisitFunc)(void* ctx, void* data);#ifdef __cplusplus
#define DECLS_BEGIN extern "C" {#define DECLS_END   }
#else
#define DECLS_BEGIN
#define DECLS_END
#endif/*__cplusplus*/#define return_if_fail(p) if(!(p)) \{printf("%s:%d Warning: "#p" failed.\n", \__func__, __LINE__); return;}
#define return_val_if_fail(p, ret) if(!(p)) \{printf("%s:%d Warning: "#p" failed.\n",\__func__, __LINE__); return (ret);}#define SAFE_FREE(p) if(p != NULL) {free(p); p = NULL;}typedef Ret (*SortFunc)(void** array, size_t nr, DataCompareFunc cmp);#endif/*TYPEDEF_H*/

darray.h

/** File:    darray.h* Author:  Li XianJing <xianjimli@hotmail.com>* Brief:   dynamic array implementation.** Copyright (c) Li XianJing** Licensed under the Academic Free License version 2.1** This program is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License as published by* the Free Software Foundation; either version 2 of the License, or* (at your option) any later version.** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the* GNU General Public License for more details.** You should have received a copy of the GNU General Public License* along with this program; if not, write to the Free Software* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*//** History:* ================================================================* 2009-01-02 Li XianJing <xianjimli@hotmail.com> created*/#include <stdio.h>
#include "typedef.h"#ifndef DARRAY_H
#define DARRAY_HDECLS_BEGINstruct _DArray;
typedef struct _DArray DArray;DArray* darray_create(DataDestroyFunc data_destroy, void* ctx);Ret    darray_insert(DArray* thiz, size_t index, void* data);
Ret    darray_prepend(DArray* thiz, void* data);
Ret    darray_append(DArray* thiz, void* data);
Ret    darray_delete(DArray* thiz, size_t index);
Ret    darray_get_by_index(DArray* thiz, size_t index, void** data);
Ret    darray_set_by_index(DArray* thiz, size_t index, void* data);
size_t darray_length(DArray* thiz);
int    darray_find(DArray* thiz, DataCompareFunc cmp, void* ctx);
Ret    darray_foreach(DArray* thiz, DataVisitFunc visit, void* ctx);void darray_destroy(DArray* thiz);DECLS_END#endif/*DARRAY_H*/

darray.c

/** File:    darray.c* Author:  Li XianJing <xianjimli@hotmail.com>* Brief:   dynamic array implementation.** Copyright (c) Li XianJing** Licensed under the Academic Free License version 2.1** This program is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License as published by* the Free Software Foundation; either version 2 of the License, or* (at your option) any later version.** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the* GNU General Public License for more details.** You should have received a copy of the GNU General Public License* along with this program; if not, write to the Free Software* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*//** History:* ================================================================* 2009-01-02 Li XianJing <xianjimli@hotmail.com> created**/#include <stdlib.h>
#include "darray.h"struct _DArray
{void** data;size_t size;size_t alloc_size;void* data_destroy_ctx;DataDestroyFunc data_destroy;
};static void darray_destroy_data(DArray* thiz, void* data)
{if(thiz->data_destroy != NULL){thiz->data_destroy(thiz->data_destroy_ctx, data);}return;
}DArray* darray_create(DataDestroyFunc data_destroy, void* ctx)
{DArray* thiz = malloc(sizeof(DArray));if(thiz != NULL){thiz->data  = NULL;thiz->size  = 0;thiz->alloc_size = 0;thiz->data_destroy = data_destroy;thiz->data_destroy_ctx = ctx;}return thiz;
}#define MIN_PRE_ALLOCATE_NR 10
static Ret darray_expand(DArray* thiz, size_t need)
{return_val_if_fail(thiz != NULL, RET_INVALID_PARAMS); if((thiz->size + need) > thiz->alloc_size){size_t alloc_size = thiz->alloc_size + (thiz->alloc_size>>1) + MIN_PRE_ALLOCATE_NR;void** data = (void**)realloc(thiz->data, sizeof(void*) * alloc_size);if(data != NULL){thiz->data = data;thiz->alloc_size = alloc_size;}}return ((thiz->size + need) <= thiz->alloc_size) ? RET_OK : RET_FAIL;
}static Ret darray_shrink(DArray* thiz)
{return_val_if_fail(thiz != NULL, RET_INVALID_PARAMS); if((thiz->size < (thiz->alloc_size >> 1)) && (thiz->alloc_size > MIN_PRE_ALLOCATE_NR)){size_t alloc_size = thiz->size + (thiz->size >> 1);void** data = (void**)realloc(thiz->data, sizeof(void*) * alloc_size);if(data != NULL){thiz->data = data;thiz->alloc_size = alloc_size;}}return RET_OK;
}Ret darray_insert(DArray* thiz, size_t index, void* data)
{Ret ret = RET_OOM;size_t cursor = index;return_val_if_fail(thiz != NULL, RET_INVALID_PARAMS); cursor = cursor < thiz->size ? cursor : thiz->size;if(darray_expand(thiz, 1) == RET_OK){size_t i = 0;for(i = thiz->size; i > cursor; i--){thiz->data[i] = thiz->data[i-1];}thiz->data[cursor] = data;thiz->size++;ret = RET_OK;}return ret;
}Ret darray_prepend(DArray* thiz, void* data)
{return darray_insert(thiz, 0, data);
}Ret darray_append(DArray* thiz, void* data)
{return darray_insert(thiz, -1, data);
}Ret darray_delete(DArray* thiz, size_t index)
{size_t i = 0;Ret ret = RET_OK;return_val_if_fail(thiz != NULL && thiz->size > index, RET_INVALID_PARAMS); darray_destroy_data(thiz, thiz->data[index]);for(i = index; (i+1) < thiz->size; i++){thiz->data[i] = thiz->data[i+1];}thiz->size--;darray_shrink(thiz);return RET_OK;
}Ret darray_get_by_index(DArray* thiz, size_t index, void** data)
{return_val_if_fail(thiz != NULL && data != NULL && index < thiz->size, RET_INVALID_PARAMS); *data = thiz->data[index];return RET_OK;
}Ret darray_set_by_index(DArray* thiz, size_t index, void* data)
{return_val_if_fail(thiz != NULL && index < thiz->size, RET_INVALID_PARAMS); thiz->data[index] = data;return RET_OK;
}size_t   darray_length(DArray* thiz)
{size_t length = 0;return_val_if_fail(thiz != NULL, 0);return thiz->size;
}Ret darray_foreach(DArray* thiz, DataVisitFunc visit, void* ctx)
{size_t i = 0; Ret ret = RET_OK;return_val_if_fail(thiz != NULL && visit != NULL, RET_INVALID_PARAMS);for(i = 0; i < thiz->size; i++){ret = visit(ctx, thiz->data[i]);}return ret;
}int      darray_find(DArray* thiz, DataCompareFunc cmp, void* ctx)
{size_t i = 0;return_val_if_fail(thiz != NULL && cmp != NULL, -1);for(i = 0; i < thiz->size; i++){if(cmp(ctx, thiz->data[i]) == 0){break;}}return i;
}void darray_destroy(DArray* thiz)
{size_t i = 0;if(thiz != NULL){for(i = 0; i < thiz->size; i++){darray_destroy_data(thiz, thiz->data[i]);}SAFE_FREE(thiz->data);SAFE_FREE(thiz);}return;
}#ifdef DARRAY_TEST#include <assert.h>static int int_cmp(void* ctx, void* data)
{return (int)data - (int)ctx;
}static Ret print_int(void* ctx, void* data)
{printf("%d ", (int)data);return RET_OK;
}static Ret check_and_dec_int(void* ctx, void* data)
{int* expected =(int*)ctx;assert(*expected == (int)data);(*expected)--;return RET_OK;
}static void test_int_darray(void)
{int i = 0;int n = 100;int data = 0;DArray* darray = darray_create(NULL, NULL);for(i = 0; i < n; i++){assert(darray_append(darray, (void*)i) == RET_OK);assert(darray_length(darray) == (i + 1));assert(darray_get_by_index(darray, i, (void**)&data) == RET_OK);assert(data == i);assert(darray_set_by_index(darray, i, (void*)(2*i)) == RET_OK);assert(darray_get_by_index(darray, i, (void**)&data) == RET_OK);assert(data == 2*i);assert(darray_set_by_index(darray, i, (void*)i) == RET_OK);assert(darray_find(darray, int_cmp, (void*)i) == i);}for(i = 0; i < n; i++){assert(darray_get_by_index(darray, 0, (void**)&data) == RET_OK);assert(data == (i));assert(darray_length(darray) == (n-i));assert(darray_delete(darray, 0) == RET_OK);assert(darray_length(darray) == (n-i-1));if((i + 1) < n){assert(darray_get_by_index(darray, 0, (void**)&data) == RET_OK);assert((int)data == (i+1));}}assert(darray_length(darray) == 0);for(i = 0; i < n; i++){assert(darray_prepend(darray, (void*)i) == RET_OK);assert(darray_length(darray) == (i + 1));assert(darray_get_by_index(darray, 0, (void**)&data) == RET_OK);assert(data == i);assert(darray_set_by_index(darray, 0, (void*)(2*i)) == RET_OK);assert(darray_get_by_index(darray, 0, (void**)&data) == RET_OK);assert(data == 2*i);assert(darray_set_by_index(darray, 0, (void*)i) == RET_OK);}i = n - 1;assert(darray_foreach(darray, check_and_dec_int, &i) == RET_OK);darray_destroy(darray);return;
}static void test_invalid_params(void)
{printf("===========Warning is normal begin==============\n");assert(darray_length(NULL) == 0);assert(darray_prepend(NULL, 0) == RET_INVALID_PARAMS);assert(darray_append(NULL, 0) == RET_INVALID_PARAMS);assert(darray_delete(NULL, 0) == RET_INVALID_PARAMS);assert(darray_insert(NULL, 0, 0) == RET_INVALID_PARAMS);assert(darray_set_by_index(NULL, 0, 0) == RET_INVALID_PARAMS);assert(darray_get_by_index(NULL, 0, NULL) == RET_INVALID_PARAMS);assert(darray_find(NULL, NULL, NULL) < 0);assert(darray_foreach(NULL, NULL, NULL) == RET_INVALID_PARAMS);printf("===========Warning is normal end==============\n");return;
}static void single_thread_test(void)
{test_int_darray();test_invalid_params();return;
}int main(int argc, char* argv[])
{single_thread_test();return 0;
}
#endif

Makefile

CFILES=darray.c
all:gcc -g -shared -lpthread $(CFILES) -o libdarray.sogcc -g -DDARRAY_TEST -lpthread $(CFILES)  -o darray_testclean:rm -f *test *.exe *.so

读书笔记 ——《系统程序员成长计划》篇7:动态数组相关推荐

  1. 读书笔记 ——《系统程序员成长计划》篇6:写的又快又好的秘诀

    说明:   本文章旨在总结备份.方便以后查询,由于是个人总结,如有不对,欢迎指正:另外,内容大部分来自网络.书籍.和各类手册,如若侵权请告知,马上删帖致歉.   QQ 群 号:513683159 [相 ...

  2. 读书笔记 ——《系统程序员成长计划》篇2:封装

    说明:   本文章旨在总结备份.方便以后查询,由于是个人总结,如有不对,欢迎指正:另外,内容大部分来自网络.书籍.和各类手册,如若侵权请告知,马上删帖致歉.   QQ 群 号:513683159 [相 ...

  3. 读书笔记 ——《系统程序员成长计划》篇3:双链表

    说明:   本文章旨在总结备份.方便以后查询,由于是个人总结,如有不对,欢迎指正:另外,内容大部分来自网络.书籍.和各类手册,如若侵权请告知,马上删帖致歉.   QQ 群 号:513683159 [相 ...

  4. 读书笔记 ——《系统程序员成长计划》篇1:代码风格

    说明:   本文章旨在总结备份.方便以后查询,由于是个人总结,如有不对,欢迎指正:另外,内容大部分来自网络.书籍.和各类手册,如若侵权请告知,马上删帖致歉.   QQ 群 号:513683159 [相 ...

  5. 读书笔记 ——《系统程序员成长计划》篇5:数据放在哪?

    说明:   本文章旨在总结备份.方便以后查询,由于是个人总结,如有不对,欢迎指正:另外,内容大部分来自网络.书籍.和各类手册,如若侵权请告知,马上删帖致歉.   QQ 群 号:513683159 [相 ...

  6. 啊哈c语言读后感500字,《麦田里的守望者》读后感读书笔记500字五篇

    <<麦田里的守望者>读后感读书笔记500字五篇>由会员分享,可在线阅读,更多相关<<麦田里的守望者>读后感读书笔记500字五篇(5页珍藏版)>请在人人文 ...

  7. 系统程序员成长计划-管道过滤器(Pipe-And-Filter)模式

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 系统程序 ...

  8. 《系统程序员成长计划》成长过程

    转载时请注明出处和作者联系方式 文章出处:http://www.limodev.cn/blog 作者联系方式:李先静 <xianjimli@gmail.com> <系统程序员成长计划 ...

  9. 系统程序员成长计划 ——学习篇7:排序算法

    目标   前面完成了动态数组的实现,现在学习几种排序算法.   实现:     ①冒泡排序②快速排序③归并排序   具体要求:     ①同时支持升序排序和降序排序.     ②同时支持多种数据类型. ...

最新文章

  1. 《深度学习:Java语言实现》一一2.6小结
  2. pandas使用dropna函数删除dataframe中列非缺失值的个数小于某一比例阈值的数据列
  3. 【原创】MIPS中断系统的板级验证及实例测试
  4. Sublime Text插件列表
  5. java精通时间_你真的精通 Java 吗?
  6. window7 修改docker安装的machine 位置
  7. Android中的onWindowFocusChanged()方法详解
  8. SqlDataReader循环取值
  9. 2010-2019年中国城市统计年鉴分享
  10. java 循环赛问题_分治法实现循环赛日程表问题
  11. 项目管理十大知识领域之项目质量管理
  12. 【5G核心网】 Network slicing 网络切片
  13. python 键盘输入负数_python输入负数
  14. FL Studio的音频录制插件Edison
  15. 深度学习中训练迭代次数理解【源码阅读技巧分享】【深度学习循环迭代理解】【for X, y in train_iter:】
  16. 如何通过Oracle官网下载jdk历史版本
  17. V2V迁移测试--VMware/VSphere环境迁移至KVM
  18. 阿里云服务器和腾讯云服务器哪个更好?多维度对比得出了结论
  19. 指数衰减函数c语言,使用Matlab实现对Ka波段卫星通信衰减 信道的性能仿真
  20. odb++ DEMO

热门文章

  1. step7建立冗余服务器站点,WinCC客户端与冗余服务器配置步骤
  2. 备赛电赛学习硬件篇(五):硬件框图、无线通信模块、OLED模块设计
  3. iOS中的3种定时器
  4. 张一鸣8年狂赚1100亿:拆解顶尖高手思维模型的秘密!
  5. 常用的Common助手类文件
  6. 前端如何实现SEO优化
  7. Unity进阶:ScriptableObject使用指南
  8. 台式电脑通过手机上网 win7 android
  9. THE MAN OF THE HOUSE-50 GREAT SHORT STORIES(一家之主-50个优秀的短故事)个人翻译
  10. 上海市python培训机构