数据结构,C语言单向链表、双向链表的学习记录(增、删、查)

声明:本文参考自今日头条用户:记录我的编程生活

原文链接:合集|C语言-数据结构与算法 - 今日头条 (toutiao.com)

 

正文:主要是记录个人学习情况,非教程,因本人也没学明白,不想误导人,代码仅供参考!废话不多说,不讲原理,自己看书,我直接上代码(欢迎批评指正)

附上gitee仓库链接:https://gitee.com/moweida/gitee_linux.git

mylist.c:

#include <stdio.h>
#include <stdlib.h>

#include "mylist.h"



//初始化单向链表
int slist_init(single_list *list)
{
	if ( NULL == list ) //判断传入的参数是否为空
	{
		printf("Illegal pointer parameter!\n");
		return -1;
	}

	list->head = list->tail = NULL;
	printf("single_list initialized successfully\n");
	return 1;
}

//初始化双向链表
int dlist_init(double_list *list)
{
	if ( NULL == list ) //判断传入的参数是否为空
	{
		printf("Illegal pointer parameter!\n");
		return -1;
	}

	list->head = list->tail = NULL;
	printf("double_list initialized successfully\n");
	return 1;
}

//单向链表头插法
int slist_head_add(single_list *list, void *data)
{
	single_list_node	*newnode = (single_list_node*)malloc(sizeof(single_list_node));
	newnode->data = data;
	newnode->next = NULL;

	if ( NULL == list ) //判断传入的参数是否为空
	{
		printf("Illegal pointer parameter!\n");
		return -1;
	}

	if ( NULL == list->head )
	{
		list->head = list->tail = newnode;
		newnode->next = NULL;
	}
	else
	{
		newnode->next = list->head; //新节点的后继指针指向头指针指向的旧(原头结点)结点
		list->head = newnode; //头指针指向新结点,成为新的头结点
	}

	printf("Add new node to the list head successfully\n");

	return 1;
}


//单向链表尾插法
int slist_tail_add(single_list *list, void *data)
{
	single_list_node	*newnode = (single_list_node*)malloc(sizeof(single_list_node)); //创建一个结点并分配内存
	newnode->data = data; //结点数据
	newnode->next = NULL; //结点后继指针

	if ( NULL == list ) //判断传入的参数是否为空
	{
		printf("Illegal pointer parameter!\n");
		return -1;
	}

	if ( NULL == list->tail ) //如果尾指针为空,代表链表没有任何结点
	{
		list-> head = list->tail = newnode; //将头指针、尾指针都指向新结点
	}
	else
	{
		list->tail->next = newnode; //否则将新结点插入链尾
		list->tail = newnode; //将尾指针指向新的链尾结点
	}

	printf("Add new node to the list tail successfully\n");

	return 1;
}


//单向链表头删法
int slist_del_head(single_list *list)
{
	if ( (NULL == list) || (NULL == list->head) ) //判断传入的参数以及链表是否为空
	{
		printf("Illegal pointer parameter!\n");
		return -1;
	}

	single_list_node *next = list->head->next; //创建一个新结点指向头结点的后继结点

	free(list->head); //释放旧的头结点
	list->head = next; //后继结点成为新的头结点
	
	printf("Delete the head node successfully\n");

	return 1;
}


//单向链表尾删法
int slist_del_tail(single_list *list)
{
	if ( (NULL == list) || (NULL == list->head) ) //判断传入的参数以及链表是否为空
	{
		printf("Illegal pointer parameter!\n");
		return -1;
	}

	single_list_node *cru = list->head; //创建一个当前结点指针,指向头结点
	single_list_node *pre = cru; //创建一个前驱结点指针,指向头结点

	while ( NULL != cru->next ) //遍历链表,寻找尾结点(后继指针为空的结点)
	{
		pre = cru; //前驱结点指针指向当前结点
		cru = cru->next; //当前结点指针指向下一结点,循环移动,直到指向尾结点
	}

	free(cru); //释放尾结点
	pre->next = NULL; //尾结点的后继指针为空
	list->tail = pre; //尾指针指向新的尾结点

	printf("Delete the tail node successfully\n");

	return 1;
}


//双向链表头插法
int dlist_head_add(double_list *list, void *data)
{
	double_list_node *newnode = (double_list_node*)malloc(sizeof(double_list_node));
	newnode->data = data;
	newnode->next = NULL;

	if ( NULL == list ) //判断传入的参数是否为空
	{
		printf("Illegal pointer parameter!\n");
		return -1;
	}

	if ( NULL == list->head )
	{
		list->head = list->tail = newnode;
		newnode->next = NULL;
	}
	else
	{
		newnode->next = list->head; //新节点的后继指针指向头指针指向的旧(原头结点)结点
		list->head->prev = newnode; //头指针的前驱指针指向新结点
		list->head = newnode; //头指针指向新结点,新结点成为头结点
		newnode->prev = NULL; //头结点的前驱为NULL
	}

	printf("Add new node to the double list head successfully\n");

	return 1;
}


//双向链表尾插法
int dlist_tail_add(double_list *list, void *data)
{
	double_list_node *newnode = (double_list_node*)malloc(sizeof(double_list_node)); //创建一个结点并分配内存
	newnode->data = data; //结点数据
	newnode->next = NULL; //结点后继指针

	if ( NULL == list ) //判断传入的参数是否为空
	{
		printf("Illegal pointer parameter!\n");
		return -1;
	}

	if ( NULL == list->tail ) //如果尾指针为空,代表链表没有任何结点
	{
		list-> head = list->tail = newnode; //将头指针、尾指针都指向新结点
		newnode->prev = newnode->next = NULL;
	}
	else
	{
		newnode->prev = list->tail; //将新结点的前驱指针指向尾结点
		list->tail->next = newnode; //否则将新结点插入链尾
		list->tail = newnode; //将尾指针指向新的链尾结点
		newnode->next = NULL; //尾结点的后继指针为NULL
	}

	printf("Add new node to the double list tail successfully\n");

	return 1;
}


//双向链表头删法
int dlist_del_head(double_list *list)
{
	if ( (NULL == list) || (NULL == list->head) ) //判断传入的参数以及链表是否为空
	{
		printf("Illegal pointer parameter!\n");
		return -1;
	}

	double_list_node *next = list->head->next; //创建一个新结点,指向头结点的后继结点

	free(list->head); //释放旧的头结点

	if ( NULL == next )
	{
		list->head = list->tail = NULL; //链表为空
	}
	else
	{
		next->prev = NULL; 
		list->head = next; //next成为新的头结点
	}

	printf("delete the head node successfully\n");

	return 1;
}


//双向链表尾删法
int dlist_del_tail(double_list *list)
{
	if ( (NULL == list) || (NULL == list->head) ) //判断传入的参数以及链表是否为空
	{
		printf("Illegal pointer parameter!\n");
		return -1;
	}

	double_list_node *prev = list->tail->prev; //创建一个当前结点指针,指向尾结点的前驱结点
	free(list->tail); //释放尾结点

	if ( NULL == prev ) //如果删除了尾结点后为空
	{
		list->head = list->tail = NULL; //链表为空
	}
	else
	{
		prev->next = NULL; //尾结点的后继为NULL
		list->tail = prev; //尾指针指向前驱结点,成为新的尾结点
	}
	printf("delete the tail node successfully\n");

	return 1;
}



//按索引查找
int slist_index_search(single_list *list, int index, void *get_data)
{
	if ( (NULL == list) || (NULL == list->head) ) //判断传入的参数以及链表是否为空
	{
		printf("Illegal pointer parameter!\n");
		return -1;
	}

	int i = 1;
	single_list_node *p = list->head; //创建一个结点指针用来遍历链表
	while ( (NULL != p) && (i < index) ) //遍历链表
	{
		p = p->next;
		i++;
	}
	if ( (NULL == p) || (i > index) ) //如果遍历完整个链表或者越界
	{
		printf("Search node of index[%d] failure\n");
		return -1;
	}

	get_data = p->data; //找到指定序号的结点,并取出其中的数据
	printf("Search node of index[%d] successfully:\n%s\n", index, get_data);
	 
	return 1;
}


//按值查找
int slist_value_search(single_list *list, void *value, void *get_data)
{
	if ( (NULL == list) || (NULL == list->head) ) //判断传入的参数以及链表是否为空
	{
		printf("Illegal pointer parameter!\n");
		return -1;
	}

	single_list_node *p = list->head; //创建一个结点指针用来遍历链表
	while ( (NULL != p) && (p->data != value) ) //遍历链表
	{
		p = p->next;
	}
	if ( (NULL == p) && (p->data != value) ) //如果遍历完整个链表都没有匹配给定数据的结点
	{
		printf("Search node of value(%s) failure\n", value);
		return -1;
	}
	get_data = p->data; //找到指定数据的结点,并取出其数据

	printf("Search node of value(%s) successfully\n", value);
	 
	return 1;
}


//按索引查找
int dlist_index_search(double_list *list, int index, void *get_data)
{
	if ( (NULL == list) || (NULL == list->head) ) //判断传入的参数以及链表是否为空
	{
		printf("Illegal pointer parameter!\n");
		return -1;
	}

	int i = 1;
	double_list_node *p = list->head; //创建一个结点指针用来遍历链表
	while ( (NULL != p) && (i < index) ) //遍历链表
	{
		p = p->next;
		i++;
	}
	if ( (NULL == p) || (i > index) ) //如果遍历完整个链表或者越界
	{
		printf("Search node of index[%d] failure\n");
		return -1;
	}

	get_data = p->data; //找到指定序号的结点,并取出其中的数据
	printf("Search node of index[%d] successfully:\n%s\n", index, get_data);
	 
	return 1;
}


//按值查找
int dlist_value_search(double_list *list, void *value, void *get_data)
{
	if ( (NULL == list) || (NULL == list->head) ) //判断传入的参数以及链表是否为空
	{
		printf("Illegal pointer parameter!\n");
		return -1;
	}

	double_list_node *p = list->head; //创建一个结点指针用来遍历链表
	while ( (NULL != p) && (p->data != value) ) //遍历链表
	{
		p = p->next;
	}
	if ( (NULL == p) && (p->data != value) ) //如果遍历完整个链表都没有匹配给定数据的结点
	{
		printf("Search node of value(%s) failure\n", value);
		return -1;
	}
	get_data = p->data; //找到指定数据的结点,并取出其数据

	printf("Search node of value(%s) successfully\n", value);
	 
	return 1;
}






mylist.h:

#include <stdio.h>
#include <stdlib.h>


//单向链表结点结构体
typedef struct single_list_node
{
	void 			        *data; //数据域
	struct single_list_node	*next; //后继指针域
}single_list_node;

//双向链表结点结构体
typedef struct double_list_node
{
	void            	    *data; //数据域
	struct double_list_node *prev; //后继指针域
	struct double_list_node *next; //后继指针域
}double_list_node;

//单链表结构体
typedef struct single_list
{
	single_list_node	*head; //头指针
	single_list_node	*tail; //尾指针
}single_list;

//双表结构体
typedef struct double_list
{
	double_list_node	*head; //头指针
	double_list_node	*tail; //尾指针
}double_list;

//初始化链表
int slist_init(single_list *list);
int dlist_init(double_list *list);

//单向链表头插法
int slist_head_add(single_list *list, void *data);
//双向链表头插法
int dlist_head_add(double_list *list, void *data);

//单向链表尾插法
int slist_tail_add(single_list *list, void *data);
//双向链表尾插法
int dlist_tail_add(double_list *list, void *data);
//单向链表头删法
int slist_del_head(single_list *list);
//双向链表头删法
int dlist_del_head(double_list *list);

//单向链表尾删法
int slist_del_tail(single_list *list);
//双向链表尾删法
int dlist_del_tail(double_list *list);

//按序号查找
int slist_index_search(single_list *list, int index, void *get_data);
//按值查找
int slist_value_search(single_list *list, void *value, void *get_data);

//按序号查找
int dlist_index_search(double_list *list, int index, void *get_data);
//按值查找
int dlist_value_search(double_list *list, void *value, void *get_data);





main.c(个人测试用)

#include <stdio.h>
#include <stdlib.h>

#include "mylist.h"

int main(int argc, char **argv)
{
	single_list 	*list1 = (single_list*)malloc(sizeof(single_list));
	double_list 	*list2 = (double_list*)malloc(sizeof(double_list));
	void	*get_data11;
	void	*get_data12;
	void	*get_data21;
	void	*get_data22;

	slist_init(list1); //初始化单向链表
	slist_head_add(list1, "single head"); //单向链表头插法
	slist_tail_add(list1, "single tail"); //单向链表尾插法
	slist_index_search(list1, 1, get_data11); //单向链表按索引查找
	slist_value_search(list1, "single head", get_data12); //单向链表按值查找
	slist_del_head(list1); //单向链表删除头结点
	slist_del_tail(list1); //单向链表删除尾结点

	dlist_init(list2); //初始化双向链表
	dlist_head_add(list2, "double head"); //双向链表头插法
	dlist_tail_add(list2, "double tail"); //双向链表尾插法
	dlist_index_search(list2, 1, get_data21); //双向链表按索引查找
	dlist_value_search(list2, "double head", get_data22); //双向链表按值查找
	dlist_del_head(list2); //双向链表删除头结点
	dlist_del_tail(list2); //双向链表删除尾结点

	return 1;
}




运行结果:(基于Linux ubuntu)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值