C语言单链表实现

最近又用C语言把单链表重新写了一遍,在这个过程中学到了不少的东西,特别是C语言内存的具体分配过程、断言的使用、C语言函数参数的传递形式。
现在把我的代码贴出来供大家参考,还 望大家不吝赐教。
/*
 *	Copyright  : 2015-2020 湖南农业大学 理学院
 * <span style="white-space:pre">	</span>File name  : link_list.c
 *	Description:
 *
 *	Author	   : Jack Huang
 *	Version	   : V1.0
 *	Date	   : Mar 28, 2016
 *
 *	History	   : 
 */
#include <assert.h>
#include <stdlib.h>
#include "link_list.h"


#undef  NDEBUG			// 调试模式


/**
 * @brief  对单链表的操作函数
 * @param
 * @retval
 */
void link_list_opreation(void)
{
	link_list *list_A = NULL;
	link_list *list_B = NULL;
	link_list *list_C = NULL;
	bool flag = false;
	Elemtype elem = 0;
	Elemtype *temp_elem = NULL;
	Elemtype data[20];
	int i = 0;

	for(i = 0; i < 20; i++)
	{
		data[i] = i;
	}
	// 输出标题
	printf("\t\tthis is a programm to test link list\n\n");
	// list_A 头表法建表
	list_A = create_link_list_tail(list_A, data, 20);
	// list_B 尾表法建表
	list_B = create_link_list_tail(list_B, data, 20);
	printf("create --- list_A is created by front_creator...\n\n");
	print_link_list(list_A);
	printf("create --- list_B is created by tail_creator...\n\n");
	print_link_list(list_B);
	// 取得单链表长度
	printf("1 --- get the length of list_A...\n");
	printf("reply --- the length of list_A = %d\n\n", get_link_list_length(list_A));

	// 查看单链表是否为空
	printf("2 --- Is the list_A is NULL?\n");

	flag = is_link_list_empty(list_A);
	if(flag == true)
	{
		printf("reply --- the answer is ture...\n\n");
	}
	else
	{
		printf("reply --- the answer is false...\n\n");
	}

	// 取得单链表元素
	printf("3 --- get the element form list_A...\n");
	flag = get_link_list_element(list_A, 2, &elem);
	if(flag == true)
	{
		printf("reply --- elem = %d\n\n", elem);
	}
	else
	{
		printf("reply --- failed...\n\n");
	}

	// 查找单链表元素 测试成功
	printf("4 --- find the element in link list...\n");
	// 返回数据域地址
	temp_elem = find_link_list_element(list_A, elem);
	if(temp_elem != NULL)
	{
		printf("reply --- temp_elem = %d\n\n", *temp_elem);
	}
	else
	{
		printf("reply --- failed...\n\n");
	}

	// 修改顺序表元素
	printf("5 --- modify element in link list...\n");
	flag = modify_link_list_element(list_A, 2, 300);
	if(flag == true)
	{
		get_link_list_element(list_A, 2, &elem);
		printf("reply --- the new value of element = %d\n\n", elem);
	}
	else
	{
		printf("reply --- failed...\n\n");
	}

	// 向单链表插入节点
	printf("6 --- insert elemnt to link list...\n");
	insert_link_list_element(list_A, 500, 11);
	flag = get_link_list_element(list_A, 11, &elem);
	if(flag == true)
	{
		printf("reply --- elem = %d\n\n", elem);
	}
	else
	{
		printf("reply --- failed...\n\n");
	}

	// 按位置删除单链表节点
	printf("7 --- delete elemnt by position...\n");
	flag = delete_link_list_element_by_index(list_A, 10, &elem);
	if(flag == true)
	{
		printf("reply --- list_A is fllowing...");
		print_link_list(list_A);
	}
	else
	{
		printf("reply --- failed\n\n");
	}

	// 按元素值删除单链表节点
	printf("8 --- delete element by value...\n");
	flag = delete_link_list_element_by_value(list_A, 300);
	if(flag == true)
	{
		printf("reply --- list_A is fllowing...\n");
		print_link_list(list_A);
	}
	else
	{
		printf("reply --- failed\n\n");
	}

	// 按元素顺序合并两个单链表
	printf("9 --- meger two srouce lists into a new sorted list...(need memory)\n");
	list_C = merge_link_list_need_memory(list_A, list_B, list_C);
	printf("reply...\n");
	print_link_list(list_C);

	printf("10 --- meger two srouce lists into a new sorted list...(don't need memory)\n");
	list_C = destory_link_list(list_C);
	list_C = merge_link_list_no_memory(list_A, list_B, list_C);
	printf("reply...\n");
	print_link_list(list_C);

	// 销毁单链表,释放堆内存
	printf("finish --- destory list_A and list_B...\n");
	list_A = destory_link_list(list_A);			// 返回NULL给list,杜绝野指针
	list_B = destory_link_list(list_B);
}


/**
 * @brief  头表法建表 已测试
 * @param
 * @retval
 */
link_list *create_link_list_front(link_list *list, Elemtype *data, int length)
{
	int i = 0;
	link_list *node = NULL;

	assert(list == NULL);
	assert(data != NULL);
	// 给头节点分配内存, 不能对指针参数修改其指向的地址,这样写有错误
	list = (link_list *)malloc(sizeof(link_list));
	assert(list != NULL);
	list->next = NULL;				// 头指针首先指向空
	for(i = 0; i < length; i++)
	{
		node = (link_list *)malloc(sizeof(link_list));	// 为新节点分配内存
		assert(node != NULL);		// 断言node分配内存是否成功
		node->data = *(data + i);	// 为新插入的节点数据域赋值
		node->next = list->next;	// 新节点接在头节点的后面
		list->next = node;			// 头节点next指针进行更新,指向新插入的元素
	}
	return list;
}



/**
 * @brief  尾表法建表	已测试
 * @param
 * @retval
 */
link_list *create_link_list_tail(link_list *list, Elemtype *data, int length)
{
	int i = 0;
	link_list *node = NULL;
	link_list *tail = NULL;				// 尾巴指针,始终指向表尾

	assert(list == NULL);
	assert(data != NULL);

	list = (link_list *)malloc(sizeof(link_list));
	tail = list;
	assert(list != NULL);
	list->next = NULL;

	for(i = 0; i < length; i++)
	{
		node = (link_list *)malloc(sizeof(link_list));
		node->data = *(data + i);		// 为新元素赋值
		tail->next = node;				// 将尾巴的next指针指向新元素
		tail = node;					// 更新尾巴指针
	}
	tail->next = NULL;					// 尾节点指向空
	return list;
}


/**
 * @brief  输出单链表	已测试
 * @param
 * @retval
 */
void print_link_list(link_list *list)
{
	int i = 0;
	link_list *node = NULL;				// 指向链表中的地第一个元素

	assert(list != NULL);
	node  = list->next;
	printf("the head address link list = %08x\n", list);
	while( node != NULL )				// 当前元素的地址不为空的,则有数据
	{
		printf("%d\t", node->data);
		if( (i + 1) % 8 == 0 )
		{
			printf("\n");
		}
		i++;
		node = node->next;
	}
	printf("\n\n");
}


/**
 * @beief  销毁单链表,释放堆内存 已测试
 * @param
 * @retval
 */
link_list *destory_link_list(link_list *list)
{
	link_list *node = NULL;
	assert(list != NULL);

	while(list->next != NULL)
	{
		node = list->next;		// 保存下一个节点的指针
		free(list);				// 释放表头内存
		list = node;			// 表头向下一个节点移动
	}
	list = NULL;
	return list;
}


/**
 * @beief  获取单链表数据长度 已测试
 * @param
 * @retval
 */
int get_link_list_length(link_list *list)
{
	int length = 0;
	link_list *node = NULL;

	assert(list != NULL);
	node = list->next;

	while(node != NULL)
	{
		length++;
		node = node->next;
	}
	return length;
}



/**
 * @brief  查看单链表是否为空
 * @param
 * @retval
 */
bool is_link_list_empty(link_list *list)
{
	assert(list != NULL);

	if(list->next != NULL)
	{
		return false;
	}
	return true;
}



/**
 * @brief  取得单链表确定位置的元素,从0开始
 * @param
 * @retval
 */
bool get_link_list_element(link_list *list, int index, Elemtype *element)
{
	int i = 0;
	link_list *node = NULL;

	assert(list != NULL);
	node = list->next;
	while( (node != NULL) && (i < index) )
	{
		i ++;
		node = node->next;
	}
	// 判断是否找到元素
	if( node == NULL )
	{
		return false;
	}
	*element = node->data;
	return true;
}




/**
 * @brief  查询顺序中的元素,查询成功返回数据域地址
 * @param
 * @retval
 */
Elemtype *find_link_list_element(link_list *list, Elemtype e)
{
	link_list *node = NULL;

	assert(list != NULL);
	node = list->next;

	while( (node != NULL) && (node->data != e) )
	{
		node = node->next;
	}

	if(node == NULL)
	{
		return NULL;
	}
	return &(node->data);
}




/**
 * @brief  修改指定位置元素的数据域
 * @param
 * @retval
 */
bool modify_link_list_element(link_list *list, int index, Elemtype new_data)
{
	int i = 0;
	link_list *node = NULL;

	assert(list != NULL);
	assert(index >= 0);
	node = list->next;

	while( (i < index) && (node != NULL) )
	{
		i++;
		node = node->next;
	}
	// 判断是否修改错误
	if(node == NULL)
	{
		return false;
	}
	node->data = new_data;
	return true;
}



/**
 * @brief  向单链表插入一个元素
 * @param
 * @retval
 */
bool insert_link_list_element(link_list *list, Elemtype data, int index)
{
	int i = 0;
	link_list *node = NULL;
	link_list *new_node = NULL;

	assert(list != NULL);
	assert(index >= 0);
	assert(index < get_link_list_length(list));
	node = list;

	while( (node != NULL) && (i < index) )
	{
		i++;
		node = node->next;
	}
	// 插入不成功
	if(node == NULL)
	{
		return false;
	}
	new_node = (link_list *)malloc(sizeof(link_list));
	assert(new_node != NULL);
	// 插入到单链表中
	new_node->next = node->next;
	node->next = new_node;
	new_node->data = data;
	return true;
}



/**
 * @brief  在单链表中删除一个元素
 * @param
 * @retval
 */
bool delete_link_list_element_by_index(link_list *list, int index, Elemtype *e)
{
	int i = 0;
	link_list *node = NULL;
	link_list *temp = NULL;
	assert(list != NULL);
	node = list->next;

	while( (node != NULL) && (i < index) )
	{
		i++;
		node = node->next;
	}
	if(node == NULL)
	{
		return false;
	}

	temp = node->next;
	node->next = temp->next;
	*e = temp->data;
	free(temp);
	temp = NULL;
	return true;
}



/**
 * @brief  在单链表中删除值为data的元素
 * @param
 * @retval
 */
bool delete_link_list_element_by_value(link_list *list, Elemtype data)
{
	link_list *node;
	link_list *temp;

	assert(list != NULL);
	node = list;

	while(node->next != NULL)
	{
		if(node->next->data == data)
		{
			temp = node->next;
			node->next = temp->next;
			free(temp);
			temp = NULL;
		}
		node = node->next;
	}
	return true;
}



/**
 * @brief  按照元素顺序合并两个有序单链表到一个新的有序单链表
 * 		   需要开辟新的空间
 * @param
 * @retval
 */
link_list  *merge_link_list_need_memory(link_list *list_src_a,
					link_list *list_src_b,
					link_list *list_destination)
{
	link_list *p_src_a = NULL;
	link_list *p_src_b = NULL;
	link_list *temp_elem = NULL;
	link_list *tail = NULL;

	assert(list_src_a->next != NULL);
	assert(list_src_b->next != NULL);
	assert(list_destination == NULL);

	p_src_a = list_src_a->next;
	p_src_b = list_src_b->next;
	// 初始化目的单链表
	list_destination = (link_list *)malloc(sizeof(link_list));
	assert(list_destination != NULL);
	// 尾巴指针初始化
	tail = list_destination;

	while( (p_src_a != NULL) && (p_src_b != NULL) )
	{
		// 给新节点分配内存
		temp_elem = (link_list *)malloc(sizeof(link_list));
		// 给新节点赋值
		if( p_src_a->data < p_src_b ->data )
		{
			temp_elem->data = p_src_a->data;
			p_src_a = p_src_a->next;
		}
		else
		{
			temp_elem->data = p_src_b->data;
			p_src_b = p_src_b->next;
		}
		tail->next = temp_elem;
		tail = temp_elem;
	}

	while(p_src_a != NULL)
	{
		temp_elem = (link_list *)malloc(sizeof(link_list));
		temp_elem->data = p_src_a->data;
		tail->next = temp_elem;
		tail = temp_elem;
		p_src_a = p_src_a->next;
	}

	while(p_src_b != NULL)
	{
		temp_elem = (link_list *)malloc(sizeof(link_list));
		temp_elem->data = p_src_b->data;
		tail->next = temp_elem;
		tail = temp_elem;
		p_src_b = p_src_b->next;
	}

	return list_destination;
}



/**
 * @brief  按照元素顺序合并两个有序单链表到一个新的有序单链表
 * 		   不需要开辟新的空间
 * @param
 * @retval
 */
link_list  *merge_link_list_no_memory(link_list *list_src_a,
				      link_list *list_src_b,
				      link_list *list_destination)
{
	link_list *p_src_a = NULL;
	link_list *p_src_b = NULL;
	link_list *tail = NULL;

	// 对参数进行处理
	assert(list_src_a->next != NULL);
	assert(list_src_b->next != NULL);
	assert(list_destination == NULL);
	// 为局部变量赋初值
	p_src_a = list_src_a->next;
	p_src_b = list_src_b->next;
	list_destination = list_src_a;
	tail = list_destination;
	// 开始插入元素
	while( (p_src_a != NULL) && (p_src_b != NULL) )
	{
		if(p_src_a->data < p_src_b->data)
		{
			tail->next = p_src_a;
			tail = p_src_a;
			p_src_a = p_src_a->next;
		}
		else
		{
			tail->next = p_src_b;
			tail = p_src_b;
			p_src_b = p_src_b->next;
		}
	}
	// 放入剩下的元素
	tail->next = p_src_a ? p_src_a : p_src_b;
	return list_destination;
}




<pre name="code" class="cpp">/*
 *	Copyright  : 2015-2020 湖南农业大学 理学院
 *  File name  : link_list.h
 *	Description:
 *
 *	Author	   : Jack Huang
 *	Version	   : 
 *	Date	   : Mar 28, 2016
 *
 *	History	   : 
 */

#ifndef LINK_LIST_H_
#define LINK_LIST_H_

#include <stdio.h>


#define MAX_SZIE 100	// 最大数据长度
#define	not_find		(int)-1
#define false 			(int)1
#define true 			(int)0

typedef int 			bool;
typedef int 			Elemtype;

typedef struct link_node
{
	Elemtype data;
	// 这是C语言中唯一允许的先使用后定义的数据结构
	struct link_node *next;
}link_list;



void link_list_opreation(void);														// 对单链表的操作函数
link_list *create_link_list_front(link_list *list, Elemtype *data, int length);		// 头插法建表
link_list *create_link_list_tail(link_list *list, Elemtype *data, int length);		// 尾插法建表
link_list *destory_link_list(link_list *list);										// 销毁单链表
bool get_link_list_element(link_list *list, int index, Elemtype *element);			// 查找单链表某个位置上的元素
int  get_link_list_length(link_list *list);											// 获取单链表数据长度
bool is_link_list_empty(link_list *list);											// 查看单链表是否为空
Elemtype *find_link_list_element(link_list *list, Elemtype e);						// 查询单链表
bool modify_link_list_element(link_list *list, int index, Elemtype new_data);
bool insert_link_list_element(link_list *list, Elemtype data, int index);			// 向单链表插入一个元素
bool delete_link_list_element_by_index(link_list *list, int index, Elemtype *e);	// 删除一个指定位置的元素,返回删除的值
bool delete_link_list_element_by_value(link_list *list, Elemtype data);				// 删除一个指定数据的元素
void print_link_list(link_list *list);												// 输出单链表
link_list *merge_link_list_need_memory(link_list *list_src_a, link_list *list_src_b, link_list *list_destination);
link_list *merge_link_list_no_memory(link_list *list_src_a, link_list *list_src_b, link_list *list_destination);

#endif /* LINK_LIST_H_ */

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值