链表的实现

链表的概念与结构

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

实际中链表结构多样,主要分为以下几种:
单向,双向
循环,非循环
带头,不带头
最常用的有两种:

无头单向非循环链表:结构简单,但实现较复杂,一般不单独存储数据

带头双向循环链表:结构复杂,一般用来单独存储数据。实际中使用的链表数据结构都是带头双向循环链表,因为实现较为简单

链表的实现

  • 无头单向不循环链表的实现

SListNode.h

#pragma once

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

typedef int SListDataType;
typedef struct SListNode//每个节点是一个结构体
{
	SListDataType _data;//数据域
	struct SListNode* _next;//指针域
}SListNode;

typedef struct SList
{
	SListNode* _head;
}SList;

void  SListInit(SList* pcb);
void SListDestroy(SList* pcb);

void  SListPushFront(SList* pcb, SListDataType x);//头插
void  SListPushBack(SList* pcb, SListDataType x);//尾插

void  SListPopFront(SList* pcb);//头删
void  SListPopBack(SList* pcb);//尾删


SListNode* SListFind(SList* pcb, SListDataType x);//查找

void SListInsertAfter(SListNode* pos, SListDataType x);//在POS的后面进行插入
void SListEraseAfter(SListNode* pos);//把pos后面的那一个删除

void SListInsertFront(SList* pcb, SListNode* pos, SListDataType x);//在pos的前面进行插入

void SListRemove(SList* pcb, SListDataType x);//找出一组数据中重复数据的第一个进行删除
void SListAllRemove(SList* pcb, SListDataType x);//删除与 X 相同的所有数据
void SListPrint(SList* pcb);//打印

SListNode.c

#include"SListNode.h"

void  SListInit(SList* pcb)
{
	assert(pcb);
	pcb->_head = NULL;
}
void SListDestroy(SList* pcb)
{
	assert(pcb);
	SListNode* cur = pcb->_head;
	SListNode* next = NULL;
	while (cur != NULL)
	{
		next = cur->_next;
		free(cur);
		cur = next;
	}
}
void  SListPushBack(SList* pcb, SListDataType x)
{
	assert(pcb);
	SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
	if (newnode == NULL)
	{
		printf("malloc error");
		exit(-1);
	}
	newnode->_data = x;
	newnode->_next = NULL;

	if (pcb->_head == NULL)//为空时
	{
		pcb->_head = newnode;
	}
	else//非空时
	{
		SListNode* cur = pcb->_head;
		while (cur->_next != NULL)
		{
			cur = cur->_next;
		}
		cur->_next = newnode;
	}
}
void  SListPopBack(SList* pcb)
{
	assert(pcb);
	SListNode* cur = pcb->_head;
	if (cur == NULL)//没有节点时
	{
		return;
	}
	else if (cur->_next == NULL)
	{
		free(cur);
		pcb->_head = NULL;
	}
	else
	{
		while (cur->_next->_next != NULL)
		{
			cur = cur->_next;
		}
		free(cur->_next);
		cur->_next = NULL;
	}
}
void  SListPushFront(SList* pcb, SListDataType x)
{
	assert(pcb);
	SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
	{
		if (newnode == NULL)
		{
			printf("newnode error");
			exit(-1);
		}
		newnode->_data = x;
		newnode->_next = NULL;

		newnode->_next = pcb->_head;
		pcb->_head = newnode;
	}
}
void  SListPopFront(SList* pcb)
{
	assert(pcb);
	SListNode* cur = pcb->_head;
	if (cur == NULL)
	{
		return;
	}
	else
	{
		pcb->_head = cur->_next;
		free(cur);
		cur = NULL;
	}
}

SListNode* SListFind(SList* pcb, SListDataType x)
{
	assert(pcb);
	SListNode* cur = pcb->_head;
	while (cur != NULL)
	{
		if (cur->_data == x)
		{
			return cur;
		}
		cur = cur->_next;
	}
	return NULL;
}
void SListInsertAfter(SListNode* pos, SListDataType x)
{
	assert(pos);
	SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
	newnode->_data = x;
	newnode->_next = NULL;
	newnode->_next = pos->_next;
	pos->_next = newnode;
}
void SListEraseAfter(SListNode* pos)
{
	assert(pos);
	if (pos->_next == NULL)
	{
		return;
	}
	else
	{
		SListNode* next = pos->_next;
		pos->_next = next->_next;
		free(next);
		next = NULL;
	}
}
void SListInsertFront(SList* pcb, SListNode* pos, SListDataType x)
{
	assert(pcb);
	assert(pos);
	SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
	newnode->_data = x;
	newnode->_next = NULL;
	SListNode* cur = pcb->_head;
	SListNode* pcur = NULL;
	while (cur != NULL)
	{
		if (cur->_data == pos->_data)
		{
			if (pcur == NULL)
			{
				pcb->_head = newnode;
				newnode->_next = cur;
			}
			else
			{
				pcur->_next = newnode;
				newnode->_next = cur;
			}
			return;
		}
		else
		{
			pcur = cur;
			cur = cur->_next;
		}
	}
}

void SListRemove(SList* pcb, SListDataType x)
{
	assert(pcb);
	SListNode* cur = pcb->_head;
	SListNode* pcur = NULL;
	while (cur != NULL)
	{
		if (cur->_data == x)
		{
			if (pcur == NULL)
				pcb->_head = cur->_next;
			else
				pcur->_next = cur->_next;
			free(cur);
			cur = NULL;
			return;
		}
		else
		{
			pcur = cur;
			cur = cur->_next;
		}
	}
}
void SListAllRemove(SList* pcb, SListDataType x)
{
	assert(pcb);
	SListNode* cur = pcb->_head;
	SListNode* prev = NULL;
	SListNode* next = NULL;
	while (cur != NULL)
	{
		if (cur->_data == x)
		{
			next = cur->_next;
			free(cur);
			cur = NULL;
			cur = next;
			if (prev == NULL)
			{
				pcb->_head = next;
			}
			else
			{
				prev->_next = cur;
			}
		}
		else
		{
			prev = cur;
			cur = cur->_next;
		}
	}
}
void SListPrint(SList* pcb)
{
	assert(pcb);
	SListNode* cur = pcb->_head;
	while (cur != NULL)
	{
		printf("%d->", cur->_data);
		cur = cur->_next;
	}
	printf("NULL\n");
}
  • 带头双向循环链表

    ListNode.h

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

typedef int LTDataType;

typedef struct ListNode 
{
	struct ListNode* _prev;
	struct ListNode* _next;
	LTDataType _data;
}ListNode;

typedef struct List 
{
	ListNode* _head;
}List;

void ListInit(List* plt);
void ListDestory(List* plt);
ListNode* BuyListNode(LTDataType x);
void ListPushFront(List* plt, LTDataType x);
void ListPushBack(List* plt, LTDataType x);
void ListPopFront(List* plt);
void ListPopBack(List* plt);
ListNode* ListFind(List* plt, LTDataType x);
void ListInsert(ListNode* pos, LTDataType x);
void ListErase(ListNode* pos);
void ListRemove(List* plt, LTDataType x);
void ListPrint(List* plt);

ListNode.c

#include"List.h"

ListNode* BuyListNode(LTDataType x)
{
	ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
	newnode->_next = NULL;
	newnode->_prev = NULL;
	newnode->_data = x;
	return newnode;
}
void ListInit(List* plt)
{
	assert(plt);
	plt->_head = NULL;
}

void ListDestory(List* plt)
{
	assert(plt);
	ListNode* head = plt->_head;
	ListNode* cur = head->_next;
	ListNode* next = NULL;
	while (cur != head)
	{
		next = cur->_next;
		free(cur);
		cur = next;
	}
}
void ListPushFront(List* plt, LTDataType x)
{
	assert(plt);
	ListNode* head = plt->_head;
	ListNode* first = head->_next;
	ListNode* newnode = BuyListNode(x);

	head->_next = newnode;
	newnode->_prev = head;
	newnode->_next = first;
	first->_prev = newnode;
}
void ListPushBack(List* plt, LTDataType x)
{
	assert(plt);
	ListNode* head = plt->_head;
	ListNode* tail = head->_prev;
	ListNode* newnode = BuyListNode(x);

	head->_prev = newnode;
	newnode->_next = head;
	newnode->_prev = tail;
	tail->_next = newnode;
}
void ListPopFront(List* plt)
{
	assert(plt);
	ListNode* head = plt->_head;
	assert(head->_next != head);
	ListNode* first = head->_next;
	ListNode* second = first->_next;
	
	free(first);
	first = NULL;
	head->_next = second;
	second->_prev = head;
}
void ListPopBack(List* plt)
{
	assert(plt);
	ListNode* head = plt->_head;
	assert(head->_prev != head);
	ListNode* Onetail = head->_prev;
	ListNode* Twotail = Onetail->_prev;

	free(Onetail);
	Onetail = NULL;
	head->_prev = Twotail;
	Twotail->_next = head;
}
ListNode* ListFind(List* plt, LTDataType x)
{
	assert(plt);
	ListNode* head = plt->_head;
	ListNode* cur = head->_next;

	while (cur != head)
	{
		if (cur->_data == x)
		{
			return cur;
		}
		cur = cur->_next;
	}
	return NULL;
}

void ListInsert(ListNode* pos, LTDataType x)
{
	assert(pos);
	ListNode* prev = pos->_prev;
	ListNode* newnode = BuyListNode(x);

	prev->_next = newnode;
	newnode->_prev = prev;
	newnode->_next = pos;
	pos->_prev = newnode;
}
void ListErase(ListNode* pos)
{
	assert(pos);
	ListNode* prev = pos->_prev;
	ListNode* next = pos->_next;

	free(pos);
	pos = NULL;
	prev->_next = next;
	next->_prev = prev;
}
void ListRemove(List* plt, LTDataType x)
{
	assert(plt);
	ListNode* head = plt->_head;
	ListNode* cur = head->_next;
	ListNode* prev = cur->_prev;
	ListNode* next = cur->_next;
	while (cur != head)
	{
		if (cur->_data == x)
		{
			free(cur);
			prev->_next = next;
			next->_prev = prev;
			cur = next;
		}
		else
		{
			cur = cur->_next;
		}
	}
}

void ListPrint(List* plt)
{
	assert(plt);
	ListNode* head = plt->_head;
	ListNode* cur = head->_next;
	while (cur != head)
	{
		printf("[%d]->", cur->_data);
		cur = cur->_next;
	}
}

链表及顺序表的比较

顺序表
优点:空间连续,支持随机访问
缺点:中间/头部插入删除时间复杂度较高,增容代价大

链表
优点:任意位置插入实践复杂度都为O(1),插入一个开辟一个空间
缺点:以节点为单位存储,不支持随机访问

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值