C语言数据结构-2.线性表之链式存储结构

本文详细介绍了线性表的链式存储结构特点、节点定义、链表概念,以及头节点与头指针的作用。同时,阐述了顺序存储与链式存储结构的优缺点对比,并提供了链表元素的插入与删除操作的实现代码,包括创建、销毁、清空、判断空、获取长度、获取元素、设置元素、遍历、搜索、插入、删除、反转等常用操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.链式结构简介

S1线性表的链式存储结构特点:
1)用任意一组地址任意的存储单元存放线性表中的数据元素。

2)节点:数据域(数据元素的信息)+指针域(指示直接后继存储位置)=节点(表示数据元素或数据元素的映像)

3)链表:以“节点的序列”表示线性表称作链表。


S2头节点以及头指针
1)有时为了操作方便,在第一个节点之前虚加以个“头节点”,
以指向头节点的指针为链表的头指针。


S3线性表的顺序存储结构与链式存储结构优缺点:
1)在分配空间上:数组分配在一块连续的数据空间上,因此在分配空间时必须确定大小;链表是一块
不连续的动态空间,通过指针来连接,因此长度可变。
2)顺序存储与链式存储优缺点:
数组优点:
1.可以利用偏移地址来访问元素,效率高,为O(1)。
2.可以使用折半方法查找元素,效率高。
数组缺点:
1.空间连续,存储效率低。
2.插入和删除元素效率比较低,而且比较麻烦。
链表优点:
1.插入和删除元素不需要移动其余元素,效率高,为O(1)。
2.不要求连续空间,空间利用率高。
链表缺点:
1.不提高随机访问元素的机制。
2.查找元素和搜索元素的效率低,最快情况为O(1),平均情况为O(N)。
总结:
因此对于经常插入和删除的操作,数据结构采用链表或者使用二叉搜索树。

S4线性表链表元素的插入与删除

注意:
删除一个节点的时候,要把被删除掉节点的内存进行释放,以免造成内存泄漏。

C语言释放内存函数是:free()

2.参考代码

1.linklist.h
<span style="font-family:Comic Sans MS;">#ifndef _LNK_LIST_H_
#define _LNK_LIST_H_

typedef int data_t;

typedef struct node_t {
	data_t data;
	struct node_t *next;
} linknode_t, *linklist_t;

/* 
 * create a empty list 
 * Input:	void
 * Output:	void
 * Return:	new list, NULL when failed 
 */
linklist_t CreateEmptyLinklist();

/* 
 * destroy a list 
 * Input:	the list to be destroied. 
 * Output:	void
 * Return:	void
 */
void	DestroyLinklist(linklist_t list);

/*
 * clear the list
 * Input:	the list to be cleared. 
 * Output:	void
 * Return:	void
 */
void	ClearLinklist(linklist_t list);

/*
 * judge if the list is empty
 * Input:	the list to be tested. 
 * Output:	void
 * Return:
 *	1:	list is empty
 *	0:	not 
 *	-1:	error
 */
int	EmptyLinklist(linklist_t list);

/*
 * get length of the list 
 * Input:	the list to be tested. 
 * Output:	void
 * Return:
 *	>=0:	length of the list
 *	-1:	means error 
 */
int	LengthLinklist(linklist_t list);

/*
 * get data of element at specified position
 * Input : 
 *	list:	the list to be operated.
 *	at:	the position where to get the element at, started from zero
 * Output:
 *	x:	the value returned
 * Return:
 *	0:	success;
 *	-1:	error   
 */
int	GetLinklist(linklist_t list, int at, data_t *x);

/*
 * set/update data of element at specified position
 * Input : 
 *	list:	the list to be operated.
 *	at:	the position at where to set the element, started with zero
 *	x:	the new data value
 * Output:	void
 * Return:
 *	0:	success;
 *	-1:	error   
 */
int	SetLinklist(linklist_t list, int at, data_t x);

/*
 * iterate through the list and print out info of each element
 * Input:
 *	list:	the list to be operated.
 * Output:	void
 * Return:	void
 */
void	VisitLinklist(linklist_t list);

/*
 * search the element by the data value and return the position
 * Input:
 *	list:	the list to be operated.
 *	x:	the data value to be compared when search
 * Output:	void
 * Return:
 *	>=0:	the position of the element found;
 *	-1:	not found or error   
 */
int	SearchLinklist(linklist_t list, data_t x);

/* 
 * insert element before the position
 * Input:
 *	list:	the list to be operated.
 *	before:	the position before which to insert the new element into, 
 *		start from zero
 *	x:	the data value 
 * Output: void
 * Return:
 *	0 : success; 
 *	-1: error 
 */
int	InsertLinklist_1(linklist_t list, int before, data_t x);

/* 
 * insert element after the position
 * Input : 
 *	list:	the list to be operated.
 *	after:	the position after which to insert the new element into,
 *		start from -1, -1 means insert to the first pos of the list
 *	x:	the data value 
 * Output:	void
 * Return:
 *	0:	success; 
 *	-1:	error 
 */
int	InsertLinklist_2(linklist_t list, int after, data_t x);

/*
 * delete the element at the position specified
 * Input: 
 *	list:	the list to be operated.
 *	at:	the position at where to delete the element, start from zero
 * Output:	void
 * Return:
 *	0:	success;
 *	!0:	not found or error
 */
int	DeleteLinklist_1(linklist_t list, int at);


/*
 * delete the element according to the data value
 * Input : 
 *	list: the list to be operated.
 *	x : the data value
 * Output: void
 * Return:
 *	>0 : success, the number of element matched and deleted;
 *	0  : not found
 *	<0 : error 
 */
int	DeleteLinklist_2(linklist_t list, data_t x);

/*
 * reverse the list
 * Input : 
 *	list: the list to be operated.
 * Output: void
 * Return: the reversed list
*/
linklist_t	ReverseLinklist(linklist_t list);

#endif /* _LNK_LIST_H_ */
</span>

2.linklist.c

<span style="font-family:Comic Sans MS;">#include <stdio.h>
#include <stdlib.h>

#include "linklist.h"

linklist_t CreateEmptyLinklist()
{
	linklist_t list;

	list = (linklist_t)malloc(sizeof(linknode_t));
	if (NULL != list) {
		list->next = NULL;
	}
	return list;
}

void	DestroyLinklist(linklist_t list)
{
	if (NULL != list) {
		ClearLinklist(list);
		free(list);
	}
}

int	GetLinklist(linklist_t list, int at, data_t *x)
{
	linknode_t *node;	/* used for iteration */
	int pos;		/* used for iteration and compare with */

	if (!list) return -1;

	/* at must >= 0 */
	if (at < 0) return -1;

	/* start from the first element */
	node = list->next;
	pos = 0;
	while (NULL != node) {

		if (at == pos) {
			if (x) {
				*x = node->data;
			}
			return 0;			
		}
		
		/* move to the next */
		node = node->next;
		pos++;
	}

	return -1;
}

int	SearchLinklist(linklist_t list, data_t x)
{
	int pos;
	linknode_t *node;

	if (!list) return -1;

	/* start from the first element */
	node = list->next;
	pos = 0;
	while (NULL != node) {

		if (x == node->data) return pos;

		/* move to the next */
		node = node->next;
		pos++;
	}
	
	/* the list is empty */
	return -1;
}

void	VisitLinklist(linklist_t list)
{
	linknode_t *node;
	int len = 0;
	
	if (!list) return;
		
	printf("list = {");

	/* start from the first element */
	node = list->next;
	while (NULL != node) {

		printf("%d->", node->data);

		/* move to the next */
		node = node->next;
		len++;
	}
	
	if (len > 0)
		printf("\b\b} \b\n");
	else
		printf("}\n");

	return;
}

int	InsertLinklist_1(linklist_t list, int before, data_t x)
{
	linknode_t *node;	/* used for iteration */
	int	before_before, pos;
	int 	found = 0;
	linknode_t *node_new;

	if (!list) return -1;

	/* before must >= 0 */
	if (before < 0) return -1;

	if (0 == before) {
		node = list;
		found = 1;
	} else {
		/* move to the position before "at" */
		before_before = before - 1;
		
		/* start from the first element */
		node = list->next;
		pos = 0;
		while (NULL != node) {

			if (before_before == pos) { 
				found = 1; /* found the position */
				break;			
			}

			/* move to the next */
			node = node->next;
			pos++;
		}
	}

	if (found) {
		node_new = malloc(sizeof(linknode_t));
		if (NULL == node_new) {
			return -1;
		}
		node_new->data = x; /* assigned value */
		
		/* insert the new node into the list */
		node_new->next = node->next;
		node->next = node_new;
		
		return 0;
		
	} else {
		return -1;
	}
}

int	DeleteLinklist_1(linklist_t list, int at)
{
	linknode_t *node, *node_next;	/* used for iteration */
	int	before_at, pos;
	int 	found = 0;

	if (!list) return -1;

	/* at must >= 0 */
	if (at < 0) return -1;

	if (0 == at) {
		node = list;
		found = 1;
		
	} else {
		/* move to the position before "at" */
		before_at = at - 1;
		
		/* start from the first element */
		node = list->next;
		pos = 0;
		while (NULL != node) {

			if (before_at == pos) { 
				found = 1; /* found the position */
				break;			
			}

			/* move to the next */
			node = node->next;
			pos++;
		}
	}

	if (found && node && node->next) {
		
		/* skip the node->next and free it */
		node_next = node->next;
		node->next = node_next->next;

		free(node_next);

		return  0;
	} else {
		return -1;
	}
}

linklist_t	ReverseLinklist(linklist_t list)
{
	linknode_t *node, *node2;

	if (!list) return NULL;
	
	/* set node pointer to the first element of the list */
	node = list->next;

	/* reset list header to NULL */
	list->next = NULL;
	
	while (NULL != node) {
		/* backup node to node2 */
		node2 = node;
		/* move node to the next */
		node = node->next;

		/* insert the node2 into the list and put
		 * it at the first position of the list 
		 */
		node2->next = list->next;
		list->next = node2;
	}
	
	return list;
}
void	ClearLinklist(linklist_t list)
{
	linklist_t next_node;
	
	if (NULL == list) return;

	while (NULL != list->next) {
		next_node = list->next;
		list->next = next_node->next;
		free(next_node);
	}

	return;
}

int	EmptyLinklist(linklist_t list)
{
	if (NULL != list) {
		if (NULL == list->next) {
			return 1;
		} else {
			return 0;
		}
	} else {
		return -1;
	}
}

int LengthLinklist(linklist_t list)
{
	int len = 0;
	linknode_t *node;

	if (!list) return -1;
		
	node = list->next;
	while (NULL != node) {
		len++;
		node = node->next;
	}

	return len;
}

int	SetLinklist(linklist_t list, int at, data_t x)
{
	linknode_t *node; /* used for iteration */
	int pos;
	int found;

	if (!list) return -1;
		
	node = list->next;
	pos = -1;
	found = 0;
	while (NULL != node) {
		pos++;
		if (at == pos) { 
			found = 1; /* found the position */
			node->data = x;
			break;			
		}
		node = node->next;
	}

	if (found) {
		return 0;
		
	} else {
		return -1;
	}
}

int	InsertLinklist_2(linklist_t list, int after, data_t x)
{
	linknode_t *node;	/* used for iteration */
	int	pos;
	int 	found = 0;
	linknode_t *node_new;

	if (!list) return -1;

	/* after must >= 0 */
	if (after < -1) return -1;

	/* start from the first element */
	node = list;
	pos = -1;
	while (NULL != node) {

		if (after == pos) { 
			found = 1; /* found the position */
			break;			
		}

		/* move to the next */
		node = node->next;
		pos++;
	}

	if (found) {
		node_new = malloc(sizeof(linknode_t));
		if (NULL == node_new) {
			return -1;
		}
		node_new->data = x; /* assigned value */
		
		/* insert the new node into the list */
		node_new->next = node->next;
		node->next = node_new;
		
		return 0;
		
	} else {
		return -1;
	}
}

int	DeleteLinklist_2(linklist_t list, data_t x)
{
	linknode_t *node, *node_prev;
	int count;

	if (!list) return -1;
		
	count = 0;
	node_prev = list;
	node = node_prev->next;
	while (NULL != node) {
		if (x == node->data) {
			count++;
			node_prev->next = node->next;
			free(node);
		} else {
			node_prev = node;
		}
		node = node_prev->next;
	}
	
	return count;
}

#if 0
/* another method to reserve the list */
linklist_t	ReverseLinklist(linklist_t list)
{
	linknode_t *node_prev, *node, *node_next;

	if (!list) return NULL;
	
	node_prev = NULL;
	node = list->next;
	while (NULL != node) {
		node_next = node->next;
	
		/* if the next node is null, the current node
		 * reaches the end of original list, 
		 * make the list head point to the current node
		 */
		if (NULL == node_next) {
			list->next = node;
		}
		
		/* reverse the linkage between nodes */		
		node->next = node_prev;
		
		/* move forward */
		node_prev = node;
		node = node_next;
	}
	
	return list;
}
#endif</span>


3.main.c

<span style="font-family:Comic Sans MS;">#include <stdio.h>
#include <stdlib.h>

#include "linklist.h"

int main(int argc, char *argv[])
{
	int i;
	data_t a[10] = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20};
	data_t x;
	
	linklist_t list;
	
	list = CreateEmptyLinklist();
	
	if (NULL == list) return -1;

	printf("insert method 1: insert each elment before\n");
	for (i = 0; i < 10; i++) {
		if (InsertLinklist_1(list, i, a[i]) < 0)
			break;
	}
	VisitLinklist(list);

	printf("clear the list\n");
	ClearLinklist(list);
	VisitLinklist(list);

	printf("insert method 1: insert each elment after\n");
	for (i = -1; i < 9; i++) {
		if (InsertLinklist_2(list, i, a[i+1]) < 0)
			break;
	}
	VisitLinklist(list);
	
	GetLinklist(list, 4, &x);
	printf("list[4] = %d\n", x);
	
	printf("updated list[4] to 100\n");
	SetLinklist(list, 4, 100);
	
	GetLinklist(list, 4, &x);
	printf("now list[4] = %d\n", x);
	
	printf("removed list[4]\n");
	DeleteLinklist_1(list, 4);
	GetLinklist(list, 4, &x);
	printf("now list[4] = %d\n", x);
	printf("and total number of list is %d\n", LengthLinklist(list));
	VisitLinklist(list);

	printf("insert \"1\" before the %dth of the list\n", 0);
	InsertLinklist_1(list, 0, 1);
	VisitLinklist(list);

	printf("reversed the list\n");
	ReverseLinklist(list);
	VisitLinklist(list);
	
	ClearLinklist(list);
	printf("after clear, total number of list is %d and ", LengthLinklist(list));
	VisitLinklist(list);
		
	DestroyLinklist(list);
	
	return 0;
}</span>



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值