【数据结构】单链表(无头单向非循环链表)各个接口的实现

  • 顺序表存在的问题:

  • 中间/头部的插入删除,时间复杂度为O(N)
  • 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗
  • 增容一般是呈2倍的增长,势必会有一定的空间浪费。

例如当前容量为100,满了以后增容到200,如果再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。所以这时就引入了链表的概念,来解决这一系列问题。

 

  • 链表的概念及结构


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

实际中链表的结构非常多样,以下情况组合起来就有8种链表结构:

  • 单向、  双向
  • 带头、不带头
  • 循环、非循环

虽然说有8种数据结构,但是我们最常用的是以下两种结构:

  • 无头单向非循环链表:

结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。

  •  带头双向循环链表:

结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了,后面我们代码实现就可以知道。

  • 单链表各个接口的实现:

  • <Slist.h>

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

typedef int SLTDataType;
typedef struct SListNode
{
	SLTDataType _data;
	struct SListNode* _next;
}SListNode;

typedef struct SList
{
	SListNode* _head;
	SListNode* _tail;
}SList;

void SListInit(SList* plist);
void SListDestroy(SList* plist);
void SListPushBack(SList* plist, SLTDataType x);
void SListPopBack(SList* plist);
void SListPushFront(SList* plist, SLTDataType x);
void SListPopFront(SList* plist);
SListNode* SListFind(SList* plist, SLTDataType x);

void SListInsertAfter(SList* plist, SListNode* pos, SLTDataType x);//在pos后面插入
void SListEraseAfter(SListNode* pos);
void SListRemove(SList* plist, SLTDataType x);

void SListPrint(SList* plist);

  • <Slist.c>

#include "SList.h"

void SListInit(SList* plist)
{
	assert(plist);
	plist->_head = NULL;
	plist->_tail = NULL;
}

void SListDestroy(SList* plist)
{
	SListNode* cur;
	assert(plist);
	cur = plist->_head;
	while (cur)
	{
		SListNode* next = cur->_next;
		free(cur);
		cur = next;
	}
	plist->_head = plist->_tail = NULL;
}

SListNode* BuySListNode(SLTDataType x)
{
	SListNode* node = (SListNode*)malloc(sizeof(SListNode));
	assert(node);
	node->_data = x;
	node->_next = NULL;
	return node;
}

void SListPushBack(SList* plist, SLTDataType x)
{
	SListNode* tail;
	assert(plist);
	//1.一个节点没有
	//2.一个以上节点
	/*if (plist->_tail == NULL)
	{
		plist->_head = plist->_tail = BuySListNode(x);
	}
	else
	{
		SListNode* newnode = BuySListNode(x);
		plist->_tail->_next = newnode;
		plist->_tail = newnode;
	}*/
	if (plist->_head == NULL)
	{
		plist->_head = BuySListNode(x);
	}
	else
	{
		tail = plist->_head;
		while (tail->_next)
		{
			tail = tail->_next;
		}
		tail->_next = BuySListNode(x);
	}
}

void SListPopBack(SList* plist)
{
	assert(plist);
	SListNode* prev, *tail;
	prev = NULL;
	tail = plist->_head;
	if (tail->_next == NULL)
	{
		free(tail);
		plist->_head = NULL;
	}
	else
	{
		while (tail->_next)
		{
			prev = tail;
			tail = tail->_next;
		}
		free(tail);
		prev->_next = NULL;
	}
}

void SListPushFront(SList* plist, SLTDataType x)
{
	SListNode* newnode;
	assert(plist);
    newnode = BuySListNode(x);
	newnode->_next = plist->_head;
	plist->_head = newnode;

}

void SListPopFront(SList* plist)
{
	SListNode* next;
	assert(plist);
    next = plist->_head->_next;
	free(plist->_head);
	plist->_head = next;
}

SListNode* SListFind(SList* plist, SLTDataType x)
{
	assert(plist);
	SListNode* cur = plist->_head;
	while (cur)
	{
		if (cur->_data== x)
		{
			return cur;
		}
		else
		{
			cur = cur->_next;
		}
	}
	return cur;
}

void SListInsertAfter(SList* plist,SListNode* pos, SLTDataType x)//在pos后面插入
{
	assert(pos);
	SListNode* next ,*newnode;
	next = pos->_next;
	newnode = BuySListNode(x);
	newnode->_next = next;
	pos->_next = newnode;
}

void SListEraseAfter(SListNode* pos)//删除pos后面的节点
{
	assert(pos);
	SListNode* next;
	if (pos->_next == NULL)
	{
		return;
	}
		next = pos->_next->_next;
		free(pos->_next);
		pos->_next = next;
}

void SListRemove(SList* plist, SLTDataType x)//删除某个给定的数
{
	assert(plist);
	if (plist->_head->_data == x)
	{
		SListPopFront(plist);
		return;
	}
	SListNode* prev = NULL;
	SListNode* cur = plist->_head;
	while (cur)
	{
		if (cur->_data == x)
		{
			prev->_next = cur->_next;
			free(cur);
			cur = NULL;
			break;
		}
		else
		{
			prev = cur;
			cur = cur->_next;
		}
	}
}

void SListPrint(SList* plist)
{
	assert(plist);
	SListNode* cur = plist->_head;
	while (cur)
	{
		printf("%d-> ", cur->_data);
		cur = cur->_next;
	}
	printf("NULL\n");
}
  • <test.c>

#include "SList.h"



void TestSList()
{
	SList sl;
	SListInit(&sl);
	SListPushBack(&sl, 1);
	SListPushBack(&sl, 2);
	SListPushBack(&sl, 3);
	SListPushBack(&sl, 4);
	SListPushBack(&sl, 5);

	SListPopBack(&sl);

	SListPushFront(&sl, 0);

	SListPopFront(&sl);
	
	SListNode* pos = SListFind(&sl, 3);
	SListInsertAfter(&sl,pos, 6);
	SListEraseAfter(pos);

	SListRemove(&sl, 3);
	SListPrint(&sl);

}


int main()
{

	TestSList();
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42270373/article/details/83033363