【小镇的技术天梯】从头写数据结构,C语言实现双向链表

【你们一定从心底里开始鄙视小镇,竟然还用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>


main.c
<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>



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值