链表的实现(单链表、双链表、循环链表)

链表:一种链式存储的线性表,用一组地址任意的存储单元存放线性表的数据元素,称存储单元为一个字节。

链表分类:

  • 单链表
  • 双链表
  • 双向循环链表

单链表

实现代码如下:

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

typedef int DataType;

typedef struct ListNode{
	DataType data;
	struct ListNode *next;
}	ListNode;

//初始化
void ListInit(ListNode **ppFirst)
{
	assert(ppFirst != NULL);
	*ppFirst = NULL;
}

//销毁
void ListDestroy(ListNode **ppFirst)
{
	*ppFirst = NULL;
}

/*
增删查改
*/
struct ListNode *CreateNode(DataType data)
{

	ListNode *newNode = (ListNode*)malloc(sizeof(ListNode));
	assert(newNode);
	newNode->data = data;
	newNode->next = NULL;

	return newNode;
}

//头插
void ListPushFront(ListNode **ppFirst,DataType data)
{
	assert(ppFirst != NULL);
	ListNode *newNode = CreateNode(data);
	newNode->data = data;
	newNode->next = *ppFirst;
	*ppFirst = newNode;
}

// 尾插
void LisstPushBack(ListNode **ppFirst, DataType data)
{
	ListNode *newNode = CreateNode(data);

	// 特殊情况,链表为空
	if (*ppFirst == NULL)
	{
		*ppFirst = newNode;
		return;
	}

	// 通常情况
	ListNode *cur = *ppFirst;
	while (cur->next != NULL)
	{
		cur = cur->next;
	}

	// cur 就是最后一个结点
	cur->next = newNode;
}

//头删 
void ListPopFront(ListNode **ppFirst)
{
	assert(ppFirst != NULL);
	assert(*ppFirst != NULL);

	ListNode *del = *ppFirst;
	*ppFirst = (*ppFirst)->next;
	free(del);
}

// 尾删
void ListPopBack(ListNode **ppFirst)
{
	assert(ppFirst != NULL); // 变量地址不为空
	assert(*ppFirst != NULL); // 不能是空链表

	// 链表中只有一个结点
	if ((*ppFirst)->next == NULL)
	{
		free(*ppFirst);
		*ppFirst = NULL;
		return;
	}

	// 正常情况
	ListNode *del;
	ListNode *cur = *ppFirst;

	while (cur->next->next != NULL)
	{
		cur = cur->next;
	}

	del = cur->next;
	cur->next = NULL;
	free(del);
}

//查找
ListNode *ListFind(ListNode *first, DataType data)
{
	//顺序查找,去遍历
	for (ListNode *cur = first; cur != NULL; cur = cur->next){
		if (cur->data == data){
			return cur;
		}
	}

	return NULL;
}

//在结点前做插入(结点 pos 肯定在链表中 && pos 不是空【链表不是空】)
void ListInsert(ListNode **ppFirst, ListNode *pos, DataType data)
{
	//头插
	if (*ppFirst == pos){
		ListPushFront(ppFirst, data);
		return;
	}

	ListNode *cur = *ppFirst;
	//找到 pos 前一个结点
	while (cur->next != pos){
		cur = cur->next;
	}

	//插入新结点
	ListNode *newNode = CreateNode(data);
	newNode->next = pos;
	cur->next = newNode;
}

//删除指定结点(结点 pos 肯定在链表中 && pos 不是空【链表不是空】)
void ListErase(ListNode **ppFirst, ListNode *pos)
{
	//头删
	if (*ppFirst == pos){
		ListPopFront(ppFirst);
		return;
	}

	ListNode *cur = *ppFirst;
	//找到 pos 前一个结点
	while (cur->next != pos){
		cur = cur->next;
	}

	//删除结点
	cur->next = pos->next;
	free(pos);
}

// 打印链表
void ListPrint(ListNode *first)
{
	for (ListNode *cur = first; cur != NULL; cur = cur->next) {
		printf("%d -> ", cur->data);
	}
	printf("NULL\n");
}

测试函数与主函数:

void TestList()
{
	ListNode *first = NULL;
	ListInit(&first);

	printf("头插:\n");
	ListPushFront(&first, 4);
	ListPushFront(&first, 3);
	ListPushFront(&first, 2);
	ListPushFront(&first, 1);
	ListPrint(first);

	printf("尾插:\n");
	LisstPushBack(&first, 5);
	LisstPushBack(&first, 6);
	LisstPushBack(&first, 7);
	ListPrint(first);

	printf("头删:\n");
	ListPopFront(&first);
	ListPrint(first);

	printf("尾删:\n");
	ListPopBack(&first);
	ListPrint(first);

	printf("查找:\n");
	ListFind(first, 5);
	ListPrint(first);
	ListFind(first, 100);
	ListPrint(first);

	printf("在指定定位置插入删除:\n");
	ListNode *result = ListFind(first, 2);
	ListInsert(&first, result, 0);
	ListPrint(first);
	ListErase(&first, result);
	ListPrint(first);
}

int main()
{
	TestList();
	return 0;
}

 

双向循环链表

实现代码如下:

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

typedef struct DListNode
{
	int data;
	struct DListNode *prev;
	struct DListNode *next;
}	DListNode;

// 初始化
void DListInit(DListNode **ppHead)
{
	assert(ppHead != NULL);
	DListNode *pHead = (DListNode *)malloc(sizeof(DListNode));

	pHead->next = pHead;
	pHead->prev = pHead;

	*ppHead = pHead;
}

// 保留头结点
void DListClear(DListNode *pHead)
{
	DListNode *cur = pHead->next;
	DListNode *next;

	while (cur != pHead)
	{
		next = cur->next;
		free(cur);
	}

	pHead->next = pHead;
	pHead->prev = pHead;
}

// 销毁头结点
void DListDestroy(DListNode **ppHead)
{
	DListClear(*ppHead);
	free(*ppHead);
	*ppHead = NULL;
}

void DListInsert(DListNode *pHead, DListNode *pos, int data)
{
	DListNode *node = (DListNode *)malloc(sizeof(DListNode));
	node->data = data;

	node->prev = pos->prev;
	node->next = pos;
	pos->prev->next = node;
	pos->prev = node;
}

// 头插
void DListPushFront(DListNode *pHead, int data)
{
	DListInsert(pHead, pHead->next, data);
}

// 尾插
void DListPushBack(DListNode *pHead, int data)
{
	DListInsert(pHead, pHead, data);
}

void DListErase(DListNode *pHead, DListNode *pos)
{
	(void)pHead;
	assert(pos != pHead);

	pos->prev->next = pos->next;
	pos->next->prev = pos->prev;
	free(pos);
}

// 头删
void DListPopFront(DListNode *pHead)
{
	// 链表为空,pHead->next == pHead;
	DListErase(pHead,pHead->next);
}

// 尾删
void DListPopBack(DListNode *pHead)
{
	DListErase(pHead, pHead->prev);
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值