数据结构与算法——单链表

1. 熟悉什么是链表,链表的分类? 

链表(链式存储)
  假如我们现在要存放一些物品,但是没有足够大的空间将所有的物品一次性放下(电脑中使用链式存储不是因为内存不够先事先说明一下...,具体原因后续会说到),同时设定我们因为脑容量很小,为了节省空间,只能记住一件物品位置。此时我们很机智的找到了解决方案:存放物品时每放置一件物品就在物品上贴一个小纸条,标明下一件物品放在那里,只记住第一件物品的位置,寻找的时候从第一件物品开始寻找,通过小纸条我们可以找到所有的物品,这就是链式存储。链表实现的时候不再像线性表一样只存储数据即可,还有下一个数据元素的地址,因此先定义一个节点类(Node),记录物品信息和下一件物品的位置,我们把物品本身叫做数据域,存储下一件物品地址信息的小纸条称为引用域。链表结构示意图如下:
  寻找物品的时候发现了一个问题,我们从一件物品找下一件物品的时候很容易,但是如果要找上一件物品就得从头开始找,真的很麻烦。为了解决这个问题我们又机智了一把,模仿之前的做法,在存放物品的时候多放置一个小纸条记录上一件物品的位置,这样就可以很快的找到上一件物品了。我们把这种方式我们称为双向链表,前面只放置一张小纸条的方式称为单向链表。


2. 熟悉链表带头结点和不带头结点的区别? (后面解释) 

带头节点:head-> p1->p2->p3 ->p1->p2->p3-> p1.....
不带头节点: p1->p2->p3 ->p1->p2->p3-> p1.....
却别还不明显吗?带头节点可以方便,快速的定位链表第1个节点
比如循环链表的时候,删除p1 的时候:
head->next = p2;
p3->next = head->next; ok?
free(p1);
思路很清晰,链表开始的第1个节点现在就是head->next 即 p2
否则没有头节点:
p3->next = p1->next;
free(p1); 


3. 完成单链表的以下基本操作: 

typedef int SDataType; 

// 链表的节点 
typedef struct SListNode 

SDataType _data; 
struct SListNode* _pNext; 
}Node, *PNode; 


// 链表的结构,给一个头指针保存链表第一个节点的地址 
typedef struct SList 

PNode _pHead; // 指向链表中的第一个节点 
}SList, *PSList; 


// 链表的初始化 
void SListInit(SList* s); 

// 在链表s最后一个节点后插入值为data的节点 
void SListPushBack(SList* s, SDataType data); 

// 删除链表s最后一个节点 
void SListPopBack(SList* s); 

// 在链表s第一个节点前插入值为data的节点 
void SListPushFront(SList* s, SDataType data); 

// 删除链表s的第一个节点 
void SListPopFront(SList* s); 

// 在链表的pos位置后插入值为data的节点 
void SListInsert(PNode pos, SDataType data); 

// 删除链表s中pos位置的节点 
void SListErase(SList* s, PNode pos); 

// 在链表中查找值为data的节点,找到返回该节点的地址,否则返回NULL 
PNode SListFind(SList* s, SDataType data); 

// 获取链表中有效节点的个数 
size_t SListSize(SList* s); 

// 检测链表是否为空 
int SListEmpty(SList* s); 

// 将链表中有效节点清空 
void SListClear(SList* s); 

// 销毁链表 
void SListDestroy(SList* s);

 

运行结果如下

 

Single_list.h

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


typedef int Datatype;
typedef struct ListNode
{
	struct ListNode* _pnext;
	Datatype _pdata;
}Node,*pNode;

void SListinit(pNode* pHead);
void Printlist(pNode* pHead);
pNode BuySListNode(Datatype data);
void SListPusfhBack(pNode* pHead, Datatype data);
void SListPopBack(pNode* pHead);
void SListPushFront(pNode* pHead, Datatype data);
void SListPopFront(pNode* pHead);
void SListInsert(pNode* pHead, pNode pos, Datatype data);
int SListEmpty(pNode* pHead);
int SListSize(pNode* pHead, Datatype data);
void SListErase(pNode* pHead, pNode pos);
pNode SListFind(pNode* pHead, Datatype data);
void SListDestroy(pNode* pHead);

 

Single_list.c

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



void SListinit(pNode* pHead) {
	assert(pHead);
	*pHead = NULL;
}
void Printlist(pNode* pHead) {
	pNode pCur = *pHead;
	if (pCur == NULL)
	{
		printf("链表为空!\n");
		return;
	}
	while (pCur) {
		printf("%d->", pCur->_pdata);
		pCur = pCur->_pnext;
	}
	printf("NULL\n");
}
pNode BuySListNode(Datatype data) {
	pNode pNewNode = (pNode)malloc(sizeof(Node));
	if (NULL == pNewNode) {
		//
		perror("pNewNode");
		//
		exit(EXIT_FAILURE);

	}
	pNewNode->_pdata = data;
	pNewNode->_pnext = NULL;
	return pNewNode;
}

void SListPushBack(pNode* pHead,Datatype data) {
	pNode pCur = *pHead;
	assert(pHead);
	if (NULL == pCur) {
		//如果链表为空直接插入
		*pHead = BuySListNode(data);
	}
	//链表不为空找到最后一个再插
	else {
		while (pCur->_pnext) {
			pCur = pCur->_pnext;
		   }
		pCur->_pnext = BuySListNode(data);
	}
}

void SListPopBack(pNode* pHead) {
	pNode pCur = *pHead;
	pNode pTail = NULL;
	assert(pHead);
	if (NULL == *pHead) {
		return;
	}
	else if(NULL==(*pHead)->_pnext){
		free(*pHead);
		*pHead = NULL;
	}
	else {
		while (pCur->_pnext) {
			pTail = pCur;
			pCur = pCur->_pnext;
		}
		pTail->_pnext = NULL;
		free(pCur);
		pCur = NULL;
	}
}
void SListPushFront(pNode* pHead, Datatype data) {
	pNode pNewNode = BuySListNode(data);
	assert(pHead);

	pNewNode->_pnext = *pHead;
	*pHead = pNewNode;

}

void SListPopFront(pNode* pHead) {
	pNode pDelNode = *pHead;
	if (NULL == *pHead) {
		assert(pHead);
		return;

	}
	else {
		*pHead = pDelNode->_pnext;
		free(pDelNode);
	}
}

void SListInsert(pNode* pHead, pNode pos, Datatype data) {
	pNode pNewNode = NULL;
	if (NULL == pHead || NULL == pos) {
		printf("链表不存在!\n");
		return;
	}
	else {
		pNewNode = BuySListNode(data);
		pNewNode->_pnext = pos->_pnext;
		pos->_pnext = pNewNode;
	}
}

int SListEmpty(pNode* pHead) {
	if (NULL == pHead) {
		return 1;
	}
	else {
		return 0;
	}
}
int SListSize(pNode* pHead, Datatype data)//找到值为data的节点个数
{
	int count = 0;
	pNode pCur = *pHead;
	if (NULL == pHead)
	{
		printf("链表为空\n");
		return 0;
	}
	while (pCur)
	{
		if (pCur->_pdata == data) {
			count++;
		}
		pCur = pCur->_pnext;
	}
	return count;
 }

void SListErase(pNode* pHead, pNode pos)
{
	pNode  pDel = NULL;
	assert(pHead);
	if (pHead == NULL || NULL == pos)
	{
		printf("输入错误\n");
		return;
	}
	else
	{
		pDel = pos->_pnext;
		pos->_pdata = pDel->_pdata;
		pos->_pnext = pDel->_pnext;
		free(pDel);
		pDel = NULL;
	}
}

pNode SListFind(pNode* pHead, Datatype data)
{
	pNode pcur = *pHead;
	if (NULL == pHead) {
		printf("链表为空!\n");
		return NULL;
	}
	while (pcur)
	{
		pcur = pcur->_pnext;
		if (pcur->_pdata == data) {
			return pcur;
		}
	}
	return NULL;
}

void SListDestory(pNode* pHead)
{
	pNode pcur = *pHead;
	pNode pnext = NULL;
	assert(pHead);
	if (NULL == pHead)
	{
		return;
	}
	else
	{
		*pHead = NULL;
		while (pcur)
		{
			pnext = pcur->_pnext;
			free(pcur);
			pcur = pnext;
		}
	}
}

int main()
{
	pNode SList, pos;
	SListinit(&SList);
	printf("初始化之后的链表为:  ");
		Printlist(&SList);

	SListPushBack(&SList, 1);
	SListPushBack(&SList, 2);
	SListPushBack(&SList, 3);
	SListPushBack(&SList, 4);
	SListPushBack(&SList, 5);
	SListPushBack(&SList, 6);
	printf("尾插之后的链表为: ");
		Printlist(&SList);


	SListPopBack(&SList);
	printf("尾删之后的链表为: ");
	Printlist(&SList);

	SListPushFront(&SList, 0);
	printf("头插后的链表为: ");
	Printlist(&SList);

	SListPopFront(&SList);
	printf("头删后的链表为: ");
	Printlist(&SList);
	  
	printf("寻找节点为3的个数:%d\n", SListSize(&SList, 3));

	pos = SListFind(&SList, 3);//pos为节点,通过Find的=函数返回一个节点进行传参
	SListInsert(&SList, pos, 9);
	printf("在节点为3的位置后插入9:\n");
	Printlist(&SList);

	SListErase(&SList, pos);
	printf("删除值为3的节点:\n");
	Printlist(&SList);

	system("pause");
	return 0;
	
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值