【你们一定从心底里开始鄙视小镇,竟然还用C语言写这些无聊基础的东西,但是我只能说,其实你们摸摸自己的心,用惯了各种语言各种类库里的各种数据结构,你们还对这些操作数据的方法有印象吗?你们有真的想过list.add()这个简单的东西还是会用到相对复杂的实现么?】
【你们真的以为动态数组就是天生存在的嘛?你们真的以为会写点业务逻辑就是程序猿了么?你们真的以为面向对象就是一切么?你们真的以为框架能实现一切业务吗?你们真的以为有了一项技术就可以不用学习混饭吃了么?】
小镇想说,恩,上面其实说的都是对的。好好做程序猿,愤世嫉俗干嘛好啦,学点基础的东西增加自己的内功。
相信大家再用python,java,php,c++和c#等语言的时候都有很多的关于数组的类和操作。当你们需要一个可以动态增加,具有弹性的数组的时候,你们可以理所当然的List newList=new List()或者是$array=array(),然后当你想增加数据的时候就list.add(1),删除的时候list.delete(1),可能时间长了时候就将这些东西当成理所当然的客观存在了。但是编程的真谛是什么?是对数据的操作,数据就是数据+数据结构,操作就是算法。当然这是在高级编程语言的范畴内,再往下细化的话,算法处理细化成cpu的控制操作器和运算器的一些列操作,数据就是计算机里面抽象出来的存储器。笼统的说也就是冯诺依曼体系,如下图所示:
小镇在后面的文章中还会介绍计算机的真正原理,计算机究竟是个什么玩意儿,计算机逻辑实现的物理层面。
今天我们来讲讲“动态数组”,其实动态数组的最普遍的原型就是链表,可以随意的添加数据而不用考虑C语言中数组的溢出。今天我们就用C语言来实现一个双向链表。
双向链表的结构如下所示:
看,这才是数据结构,下面的代码中能够清楚的看到一些对内存的操作(指针方面的),而不是抽象出来的动态数组的类和对象。相信大家都学过c语言,双向链表应该是最基础的课程,我写了一个代码给大家参考参考,大家有空自己练练。
首先,我定义的struct叫z_array。总共三个文件,分别是zarray.h zarray.c main.c 编译请用gcc -o xxx main.c命令即可,连接器自动帮你找头文件什么的。gcc的具体工作原理这里不讲。
zarray.h
<span style="font-size:18px;">#ifndef __Z_ARRAY_H
#define __Z_ARRAY_H
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <memory.h>
typedef struct z_array_struct
{
int num;
struct z_array_struct *next, *prev;
}z_array;
/*
* *创建双向链表节点
*/
z_array* create_z_array_node( int value );
void delete_all_z_array_node( z_array** z_node );
z_array* find_data_in_z_array( const z_array* z_node, int data );
int delete_data_from_z_array( z_array** zznode, int data );
int insert_data_into_z_array( z_array** zz_node, int data );
int count_number_in_z_array( const z_array* znode );
void print_z_array( const z_array* z_node );
#endif /* __Z_ARRAY_H */</span>
【头文件定义一些方法和数据结构,数据结构就是两个指针 一个值。ifndef防止头文件重复引用】zarray.c
<span style="font-size:18px;">#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <memory.h>
#include "zarray.h"
/*
* 创建双向链表节点
*/
z_array* create_z_array_node( int value )
{
z_array* z_node = NULL;
z_node = (z_array *) malloc( sizeof(z_array) );
assert( NULL != z_node );
memset( z_node, 0, sizeof(z_node) ); /* z_node清零 */
z_node->num = value;
return(z_node);
}
/*
* 删除所有的节点
* 用到了递归
*/
void delete_all_z_array_node( z_array** z_node )
{
z_array* current_node;
if ( NULL == *z_node )
return;
current_node = *z_node;
*z_node = current_node->next;
free( current_node );
delete_all_z_array_node( z_node );
}
/* 找到相应数据的节点 */
z_array* find_data_in_z_array( const z_array* z_node, int data )
{
z_array* current_node = NULL;
if ( NULL == z_node )
return(NULL);
current_node = (z_array *) z_node;
while ( NULL != current_node )
{
if ( data == current_node->num )
return(current_node);
current_node = current_node->next;
}
return(NULL);
}
/* 删除相应数据的节点 */
int delete_data_from_z_array( z_array** zznode, int data )
{
z_array * cnode = *zznode;
if ( zznode == NULL || *zznode == NULL )
return(0);
cnode = find_data_in_z_array( *zznode, data );
if ( cnode == NULL )
return(0);
if ( cnode->next == NULL || cnode->prev == NULL )
{
if ( cnode->next == NULL && cnode->prev == NULL )
free( *zznode );
else if ( cnode->next == NULL )
(cnode->prev)->next = cnode->next;
else
(cnode->next)->prev = cnode->prev;
/* 将head指向后面一个节点 */
*zznode = cnode->next;
return(1);
}else {
(cnode->prev)->next = cnode->next;
(cnode->next)->prev = cnode->prev;
}
free( cnode );
return(1);
}
/* 在链表末尾插入数据 */
int insert_data_into_z_array( z_array** zz_node, int data )
{
z_array * current_node;
z_array * current_index;
if ( NULL == zz_node )
return(0);
if ( NULL == *zz_node )
{
current_node = create_z_array_node( data );
*zz_node = current_node;
(*zz_node)->prev = (*zz_node)->next = NULL; /* 初始化起点,两边为空 */
return(1);
}
if ( find_data_in_z_array( *zz_node, data ) != NULL )
return(0);
/* 创造一个节点 */
current_node = create_z_array_node( data );
current_index = *zz_node;
/* 指针移到最后 */
while ( current_index->next != NULL )
current_index = current_index->next;
current_node->prev = current_index;
current_node->next = current_index->next;
current_index->next = current_node;
return(1);
}
/* 统计双向链表中的个数 */
int count_number_in_z_array( const z_array* znode )
{
int count = 0;
z_array * cnode = (z_array *) znode;
while ( cnode != NULL )
{
count++;
cnode = cnode->next;
}
return(count);
}
/* 打印数组 */
void print_z_array( const z_array* z_node )
{
z_array* cnode = (z_array *) z_node;
while ( cnode != NULL )
{
printf( "%d ", cnode->num );
cnode = cnode->next;
}
}
</span>
<span style="font-size:18px;">#include "zarray.h"
int main()
{
z_array* head = create_z_array_node( 5 );
insert_data_into_z_array( &head, 6 );
insert_data_into_z_array( &head, 7 );
insert_data_into_z_array( &head, 8 );
delete_data_from_z_array( &head, 6 );
delete_data_from_z_array( &head, 7 );
delete_data_from_z_array( &head, 5 );
delete_data_from_z_array( &head, 8 );
print_z_array( head );
printf( "\n" );
int z_array_count = count_number_in_z_array( head );
printf( "双向链表中的节点个数为%d\n", z_array_count );
}
</span>