单链表和双向链表实现


一、单链表

单向不带头不循环链表的实现

结构定义

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLTDataType;

struct SListNode
{
	SLTDataType data;
	struct SLNode* next;
};
typedef struct SListNode SLTNode;

动态申请一个节点

// 动态申请一个节点
SLTNode* BuySListNode(SLTDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL)
	{
		exit(-1);
	}
	newnode->next = NULL;
	newnode->data = x;
	return newnode;
}

单链表打印

// 单链表打印
void SListPrint(SLTNode* phead)
{
	while (phead)
	{
		printf("%d->", phead->data);
		phead = phead->next;
	}
	printf("NULL\n");
}

单链表尾插

// 单链表尾插
void SListPushBack(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	//1.没有结点
	//2.至少一个结点
	SLTNode* newnode = BuySListNode(x);
	if (*pphead == NULL)
	{
		//没有结点		
		*pphead = newnode;
	}
	else
	{
		//有结点,找尾
		SLTNode* tail = *pphead;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		tail->next = newnode;
	}
}

单链表头插

// 单链表的头插
void SListPushFront(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	//链表是否为空不影响头插
	SLTNode* newnode = BuySListNode(x);
	newnode->next = *pphead;
	*pphead = newnode;
}

单链表尾删

// 单链表的尾删
void SListPopBack(SLTNode** pphead)
{
	assert(pphead);
	assert(*pphead);//不能没有结点
	//如果只有一个结点
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		//不止一个结点
		SLTNode* prev = *pphead;//存放最后一个结点的前一个
		SLTNode* tail = *pphead;//找尾
		while (tail->next != NULL)
		{
			prev = tail;
			tail = tail->next;
		}
		prev->next = NULL;
		free(tail);
	}
}

单链表头删

// 单链表头删
void SListPopFront(SLTNode** pphead)
{
	assert(pphead);
	assert(*pphead);//不能没有结点
	
	//有一个结点也相同
	SLTNode* next = (*pphead)->next;
	free(*pphead);
	*pphead = next;
}

单链表查找

// 单链表查找
SLTNode* SListFind(SLTNode* phead, SLTDataType x)
{	
	while (phead != NULL)
	{
		if (phead->data == x)
			break;
		phead = phead->next;
	}
	return phead;
}

在pos位置之前去插入一个节点

// 在pos位置之前去插入一个节点
void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	assert(pphead && *pphead && pos);

	SLTNode* newnode = BuySListNode(x);	
	if (*pphead == pos)
	{
		//只有一个结点,头插
		newnode->next = *pphead;
		*pphead = newnode;
	}
	else
	{
		SLTNode* prev = *pphead;//存放pos结点的前一个
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = newnode;
		newnode->next = pos;
	}
}

删除在pos位置节点

// 删除在pos位置节点
void SListErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead && *pphead && pos);
	//只有一个结点
	if (*pphead == pos)
	{
		SLTNode* next = (*pphead)->next;//存放pos结点的下一个
		free(*pphead);
		*pphead = next;
	}
	else
	{
		SLTNode* prev = *pphead;//存放pos结点的前一个

		while (prev != pos)
		{
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
		
		//也可如下
		//SLTNode* tail = *pphead;//找pos
		//while (tail->next != NULL)
		//{
		//	if (tail == pos)
		//		break;
		//	prev = tail;
		//	tail = tail->next;
		//}
		//prev->next = tail->next;
		//free(tail);
	}
}

单链表在pos位置之后插入x

// 单链表在pos位置之后插入x
void SListInsertAfter(SLTNode* pos, SLTDataType x)
{
	assert(pos);
	SLTNode* newnode = BuySListNode(x);
	SLTNode* next = pos->next;
	pos->next = newnode;
	newnode->next = next;
}

单链表删除pos位置之后的值

// 单链表删除pos位置之后的值
void SListEraseAfter(SLTNode* pos)
{
	assert(pos);
	assert(pos->next);//pos后面不能没有
	//链接删除结点左右两个结点
	SLTNode* next = pos->next;
	pos->next = next->next;
	free(next);
}

单链表销毁

void SListDestory(SLTNode** pphead)
{
	SLTNode* next = *pphead;
	while (next != NULL)
	{
		SLTNode* temp = next;
		next = next->next;
		free(temp);		
	}
	*pphead = NULL;
}

二、双向链表

双向带头循环链表的实现

结构定义

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
//带头结点的双向循环链表
typedef int LTDataType;

typedef struct ListNode
{
	LTDataType data;
	struct ListNode* next;
	struct ListNode* prev;
}LTNode;

初始化链表

//初始化链表
LTNode* ListInit()
{
	//创建头结点
	LTNode* head = (LTNode*)malloc(sizeof(LTNode));
	if (head == NULL)
		exit(-1);

	head->next = head;
	head->prev = head;
	
	return head;
}

双向链表打印

// 双向链表打印
void ListPrint(LTNode* phead)
{
	assert(phead);
	LTNode* sur = phead->next;
	while (sur != phead)
	{
		printf("%d->", sur->data);
		sur = sur->next;
	}
	printf("NULL\n");
}

创建一个新的结点

//创建一个新的结点
LTNode* BuyListNode(LTDataType x)
{
	//创建结点
	LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
	if (newnode == NULL)
		exit(-1);
	newnode->data = x;
	newnode->next = NULL;
	newnode->prev = NULL;
	return newnode;
}

双向链表尾插

// 双向链表尾插
void ListPushBack(LTNode* phead, LTDataType x)
{
	LTNode* newnode = BuyListNode(x);
	//直接链接,不用考虑多余情况
	LTNode* tail = phead->prev;
	tail->next = newnode;
	newnode->prev = tail;
	phead->prev = newnode;
	newnode->next = phead;
}

双向链表尾删

// 双向链表尾删
void ListPopBack(LTNode* phead)
{
	//头结点不为空,并且链表不为空
	assert(phead && phead->next != phead);

	LTNode* tail = phead->prev;
	LTNode* tailPrev = tail->prev;//尾的前一个
	tailPrev->next = phead;
	phead->prev = tailPrev;
	free(tail);
}

双向链表头插

// 双向链表头插
void ListPushFront(LTNode* phead, LTDataType x)
{
	assert(phead);
	LTNode* newnode = BuyListNode(x);
	LTNode* first = phead->next;//第一个有效结点

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

双向链表头删

// 双向链表头删
void ListPopFront(LTNode* phead)
{
	//头结点不为空,并且链表不为空
	assert(phead && phead->next != phead);

	LTNode* first = phead->next;
	LTNode* firstNext = first->next;

	phead->next = firstNext;
	firstNext->prev = phead;
	free(first);
}

双向链表查找

// 双向链表查找
LTNode* ListFind(LTNode* phead, LTDataType x)
{
	assert(phead && phead->next != phead);
	LTNode* temp = phead->next;
	while (temp != phead)
	{
		if (temp->data == x)
			return temp;
		temp = temp->next;
	}
	//找不到
	return NULL;
}

双向链表在pos的前面进行插入

// 双向链表在pos的前面进行插入
void ListInsert(LTNode* pos, LTDataType x)
{
	assert(pos);

	LTNode* newnode = BuyListNode(x);
	LTNode* posPrev = pos->prev;
	
	newnode->prev = posPrev;
	posPrev->next = newnode;
	newnode->next = pos;
	pos->prev = newnode;
}

双向链表删除pos位置的节点

// 双向链表删除pos位置的节点
void ListErase(LTNode* pos)
{
	assert(pos);
	LTNode* posPrev = pos->prev;
	posPrev->next = pos->next;
	pos->next->prev = posPrev;
	free(pos);
}

摧毁链表

// 摧毁链表
void ListDestroy(LTNode* phead)
{
	assert(phead);
	LTNode* sur = phead->next;
	LTNode* next = NULL;
	while (sur != phead)
	{
		next = sur->next;
		free(sur);
		sur = next;
	}
	free(phead);
}

为了更快捷的写出双向链表,可以仅靠ListErase和ListInsert来实现相关的插入删除操作。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

s_persist

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值