数据结构 链表..及链表与顺序表的区别

在这里插入代码片1. 熟悉什么是链表,链表的分类?
`链表是一种物理存储结构上非连续,顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的,
在这里插入图片描述
2.链表带头结点和不带头结点的区别?
带头结点可以快速定位链表,在插入和删除第一个结点时都会更加方便.,带头结点时,头指针指向头结点,不带头结点时,头指针指向第一个结点的地址.

3.以链表中最常见的2中链表为例,进行一些操作:

不循环单链表

#pragma once

typedef int SDataType;

//链表的节点
typedef struct SListNode
{
	SDataType _data;
	struct SListNode* _pNext;
}Node,*PNode;

typedef struct SList
{
	PNode _pHead;
}SList, * PSList;
//初始化
void SListInit(SList* s);
//尾插
void SListPushBack(SList* s, SDataType data);
//尾删
void SListPopBack(SList* s);
//头插
void SListPushFront(SList* s, SDataType data);
//头删
void SListPopFront(SList* s);
//任意位置的插入
void SListInsert(SList*s,PNode pos, SDataType data);
//任意位置的删除
void SListErase(SList* s, PNode pos);
//结点数
int SListSize(SList* s);
//判空
int SListEmpty(SList* s);
//删除第一个值为data的结点
void SListRemove(SList* s, SDataType data);

#include "SList.h"
#include <stdio.h>
#include <assert.h>

void SListInit(SList* s)
{
	assert(s);
	s->_pHead = NULL;
}

PNode BuySListNode(SDataType data)
{
	PNode pNewNode = (PNode)malloc(sizeof(PNode));
	if (pNewNode == NULL)
	{
		assert(0);
		return NULL;
	}
	pNewNode->_data = data;
	pNewNode->_pNext = NULL;
	return pNewNode;
}

void SListPushBack(SList* s, SDataType data)
{
	assert(s);
	PNode pNewNode = BuySListNode(data);
	if (NULL == s->_pHead)
	{
		//若为空链表,则新增节点为头节点
		s->_pHead = pNewNode;
	}
	else
	{
		//链表非空,找最后一个节点
		PNode pCur = s->_pHead;
		while (pCur->_pNext)
			pCur = pCur->_pNext;
		pCur->_pNext = pNewNode;
	}
}

void SListPopBack(SList* s)
{
	assert(s);
	if (s->_pHead == NULL)
		//空链表
		return;
	else if(NULL ==s->_pHead->_pNext)
	{
		//一个节点
		free(s->_pHead);
		s->_pHead;
	}
	else
	{
		//多个节点
		PNode pPre = NULL;
		PNode pCur = s->_pHead;
		while (pCur->_pNext)
		{
			pPre = pCur;
			pCur = pCur->_pNext;
		}
		free(pCur);
		pPre->_pNext = NULL;
	}
}

void SListPushFront(SList* s, SDataType data)
{
	assert(s);
	PNode pNewNode = BuySListNode(data);
	pNewNode->_pNext = s->_pHead;
	s->_pHead = pNewNode;
}

void SListPopFront(SList* s)
{
	assert(s);
	if (s->_pHead == NULL);
		//空链表
		
	else if (s->_pHead->_pNext == NULL)
	{
		free(s->_pHead);
	}
	else
	{
		s->_pHead = s->_pHead->_pNext;
		free(s->_pHead);
	}
	return;
}

void SListInsert(SList* s,PNode pos, SDataType data)
{
	assert(s);
	if (pos == NULL)
		return;
	PNode pNewNode = BuySListNode(data);
	pNewNode->_pNext = pos->_pNext;
	pos->_pNext = pNewNode;
}

void SListErase(SList* s, PNode pos)
{
	assert(s);
	if (s->_pHead == NULL||pos == NULL)
		return;
	else if(s->_pHead==pos)
	{
		s->_pHead = s->_pHead->_pNext;
	}
	else
	{
		PNode pPrePos = s->_pHead;
		while (pPrePos->_pNext != pos)
			pPrePos = pPrePos->_pNext;
		pPrePos->_pNext = pos->_pNext;
	}
	free(pos);
}

int SListSize(SList* s)
{
	assert(s);
	if (s->_pHead == NULL)
		return 0;
	else
	{
		int count = 1;
		PNode pCur = s->_pHead;
		while (pCur->_pNext)
		{
			pCur = pCur->_pNext;
			++count;
			return count;
		}
	}
}

int SListEmpty(SList* s)
{
	assert(s);
	return NULL == s->_pHead;
}

void SListRemove(SList* s, SDataType data)
{
	assert(s);
	if (s->_pHead == NULL)
		return;
	PNode pPre = NULL;
	PNode pCur = s->_pHead;
	while (pCur)
	{
		if (pCur->_data == data)
		{
			if (pCur == s->_pHead)
			{
				s->_pHead = pCur->_pNext;
			}
			else
			{
				pPre->_pNext = pCur->_pNext;
			}
			free(pCur);
			break;
		}
		else
		{
			pPre = pCur;
			pCur = pCur->_pNext;
		}
	}
	return;
}

循环双链表

#pragma once

typedef int DLDataType;

typedef  struct DListNode
{
	struct DListNode* _pNext;
	struct DListNode* _pPre;
	DLDataType _data;
}DLNode, * PDLNode;

void DListInit(PDLNode* pHead);
void DListPushBack(PDLNode pHead, DLDataType data);
void DListPopBack(PDLNode pHead);
void DListPushFront(PDLNode pHead, DLDataType data);
void DListPopFront(PDLNode pHead);
void DLishInsert(PDLNode pos, DLDataType data);
void DLishErase(PDLNode pos);
void DLishClear(PDLNode pHead);
void DLishDestroy(PDLNode* pHead);

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

#include "DList.h"

void DListInit(PDLNode* pHead) 
{
	assert(pHead);
	*pHead = (PDLNode)malloc(sizeof(DLNode));
	if (NULL == *pHead) 
	{
		assert(0);
		return ;
	}
	(*pHead)->_pNext = *pHead;
	(*pHead)->_pPre = *pHead;
}

PDLNode BuyDistNode(DLDataType data)
{
	PDLNode pNewNode = (PDLNode)malloc(sizeof(DLNode));
	if (NULL == pNewNode)
	{
		assert(0);
		return;
	}
	pNewNode->_data = data;
	pNewNode->_pNext = NULL;
	pNewNode->_pPre = NULL;
	return pNewNode;
}

void DListPushBack(PDLNode pHead, DLDataType data)
{
	PDLNode pNewNode = BuyDistNode(data);
	pNewNode->_pNext = pHead;
	pNewNode->_pPre = pHead->_pPre;
	pHead->_pPre->_pNext = pNewNode;
	pHead->_pPre = pNewNode;
}

void DListPopBack(PDLNode pHead)
{
	assert(pHead);
	if (pHead == pHead->_pNext)
		return;
	PDLNode pDelNode = pHead->_pPre;
	pDelNode->_pPre->_pNext = pHead;
	pHead->_pPre = pDelNode->_pPre;
	free(pDelNode);
}

void DListPushFront(PDLNode pHead, DLDataType data)
{
	PDLNode pNewNode = BuyDListNode(data);
	pNewNode->_pNext = pHead->_pNext;
	pNewNode->_pPre = pHead;
	pHead->_pNext = pNewNode;
	pNewNode->_pNext->_pPre = pNewNode;
}

void DListPopFront(PDLNode pHead)
{
	assert(pHead);
	if (pHead->_pNext == pHead)
		return;
	PDLNode pDelNode = pHead->_pNext;
	pHead->_pNext = pDelNode->_pNext;
	pDelNode->_pNext->_pPre = pHead;
	free(pDelNode);
}

void DLishInsert(PDLNode pos, DLDataType data)
{
	if (pos==NULL)
		return;
	PDLNode pNewNode = BuyDListNode(data);
	pNewNode->_pNext = pos;
	pNewNode->_pPre = pos->_pPre;
	pos->_pPre = pNewNode;
	pNewNode->_pPre->_pNext = pNewNode;
}

void DLishErase(PDLNode pos)
{
	if (pos == NULL)
		return;
	pos->_pNext->_pPre = pos->_pPre;
	pos->_pPre->_pNext = pos->_pNext;
	
	free(pos);
}

void DLishClear(PDLNode pHead)
{
	PDLNode pCur = pHead->_pNext;
	while (pCur != pHead)
	{
		pHead->_pNext = pCur->_pNext;
		free(pCur);
		pCur = pHead->_pNext;
	}
	pHead->_pNext;
	pHead->_pPre = pHead;
}

void DLishDestroy(PDLNode* pHead)
{
	DListClear(*pHead);
	free(*pHead);
	*pHead = NULL;
}

链表与顺序表的区别:
1,首先:他们名称不同(^ - ^);

2,尾插和尾删时:
顺序表的时间复杂度为O(1),而链表中不带头结点的链表时间复杂度为O(N),循环链表为O(1);

3.在任意位置插入和删除时:
顺序表的时间复杂度为O(N),而链表的时间复杂度为O(1);

4.顺序表支持随机访问,而链表不支持随机访问.

5,关于底层空间:顺序表的底层空间一般连续,而链表的底层空间不连续

6.顺序表在插入元素时可能需要扩容,而链表不需要.

7.在空间利用率方面,顺序表除非扩容,否则不需要申请空间,而链表每次插入都需要申请空间.

8.顺序表的缓存利用率高

9.在应用方面不同

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值