数据结构——链表

1. 什么是链表?

链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。

2. 链表的分类?

单向或双向

 

 

带头或不带头

 

循环或非循环

 

单链表实现:

1. 动态申请一个节点 

// 动态申请一个节点
SListNode* BuySListNode(SLTDataType x)
{
	SListNode* newNode = (SListNode*)malloc(sizeof(SListNode));

	if (newNode == NULL)
	{
		perror("malloc failed");
		exit(-1);
	}

	newNode->data = x;
	newNode->next = NULL;

	return newNode;
}

2. 单链表打印 

// 单链表打印
void SListPrint(SListNode* phead)
{
	SListNode* cur = phead;

	while (cur != NULL)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}

3. 单链表尾插

// 单链表尾插
void SListPushBack(SListNode** pphead, SLTDataType x)
{
	SListNode* newNode =  BuySListNode(x);
	SListNode* tail = *pphead;

	if (tail == NULL)
	{
		*pphead = newNode;
	}
	else
	{
		while (tail->next != NULL)
		{
			tail = tail->next;
		}

		tail->next = newNode;
	}
}

4. 单链表头插

// 单链表的头插
void SListPushFront(SListNode** pphead, SLTDataType x)
{
	SListNode* newNode = BuySListNode(x);

	newNode->next = *pphead;
	*pphead = newNode;
}

5. 单链表尾删 

// 单链表的尾删
void SListPopBack(SListNode** pphead)
{
	assert(*pphead);

	SListNode* tail = *pphead;
	SListNode* tailPrev = NULL;

	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		while (tail->next != NULL)
		{
			tailPrev = tail;
			tail = tail->next;
		}
		free(tail);
		tailPrev->next = NULL;
	}
}

6. 单链表头删

// 单链表头删
void SListPopFront(SListNode** pphead)
{
	assert(*pphead);

	SListNode* newHead = (*pphead)->next;
	free(*pphead);
	*pphead = newHead;
}

7. 单链表查找

// 单链表查找
SListNode* SListFind(SListNode* phead, SLTDataType x)
{
	assert(phead);

	SListNode* newNode = BuySListNode(x);

	SListNode* cur = phead;

	while (cur != NULL)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}

	return NULL;
}

8. 单链表插入

// 单链表在pos位置之后插入x
void SListInsertAfter(SListNode** pphead, SListNode* pos, SLTDataType x)
{
	assert(pos);

	SListNode* newNode = BuySListNode(x);

	newNode->next = pos->next;
	pos->next = newNode;
}

9. 单链表删除

// 单链表删除pos位置之后的值
void SListEraseAfter(SListNode** pphead, SListNode* pos)
{
	assert(*pphead);
	assert(pos);

	SListNode* posNext = pos->next;
	if (posNext != NULL)
	{
		pos->next = posNext->next;
	}

	free(posNext);
}

10. 单链表销毁

// 单链表的销毁
void SListDestroy(SListNode** pphead)
{
	SListNode* cur = *pphead;
	SListNode* curPrev = NULL;

	while (cur != NULL)
	{
		curPrev = cur;
		cur = cur->next;
		free(curPrev);
	}
	*pphead = NULL;
}

双向链表实现: 

 1. 创建头节点

// 创建返回链表的头结点.
ListNode* ListCreate()
{
	ListNode* phead = (ListNode*)malloc(sizeof(ListNode));

	phead->next = phead;
	phead->prev = phead;
	phead->data = -1;

	return phead;
}

2. 双链表销毁

// 双向链表销毁
void ListDestory(ListNode* phead)
{
	assert(phead);

	ListNode* cur = phead->next;

	while (cur != phead)
	{
		ListNode* next = cur->next;
		free(cur);
		cur = next;
	}
	free(phead);
}

3. 双链表打印

// 双向链表打印
void ListPrint(ListNode* phead)
{
	assert(phead);

	ListNode* cur = phead->next;

	printf("head<=>");
	while (cur != phead)
	{
		printf("%d<=>", cur->data);
		cur = cur->next;
	}
	putchar('\n');
}

4. 双链表尾插

// 双向链表尾插
void ListPushBack(ListNode* phead, LTDataType x)
{
	assert(phead);

	ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));

	newnode->data = x;
	
	ListNode* tail = phead->prev;

	tail->next = newnode;
	newnode->prev = tail;

	newnode->next = phead;
	phead->prev = newnode;
}

5. 双链表头插

// 双向链表头插
void ListPushFront(ListNode* phead, LTDataType x)
{
	assert(phead);

	ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));

	newnode->data = x;

	ListNode* first = phead->next;

	phead->next = newnode;
	newnode->prev = phead;

	newnode->next = first;
	first->prev = newnode;
}

6. 双链表头删

// 双向链表头删
void ListPopFront(ListNode* phead)
{
	assert(phead);
	ListNode* first = phead->next;
	assert(first != phead);  // 至少有一个元素

	phead->next = first->next;
	first->next->prev = phead;

	free(first);
}

7. 双链表查找

// 双向链表查找
ListNode* ListFind(ListNode* phead, LTDataType x)
{
	assert(phead);
	ListNode* cur = phead->next;
	assert(cur != phead); // 至少有一个元素

	while (cur != phead)
	{
		if (cur->data == x)
		{
			return cur;
		}

		cur = cur->next;
	}

	return NULL;
}

8. 双链表插入

// 双向链表在pos的前面进行插入
void ListInsert(ListNode* phead, ListNode* pos, LTDataType x)
{
	assert(phead);
	assert(pos);  // 元素必须存在
	assert(phead->next != phead); // 至少有一个元素

	ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));

	newnode->data = x;

	ListNode* prev = pos->prev;

	prev->next = newnode;
	newnode->prev = prev;

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

9.  双链表删除

// 双向链表删除pos位置的节点
void ListErase(ListNode* phead, ListNode* pos)
{
	assert(phead);
	assert(phead->next != phead); // 至少有一个元素
	assert(pos);  // 元素必须存在

	ListNode* prev = pos->prev;
	ListNode* next = pos->next;

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

	free(pos);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值