最近又用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_ */