无头单链表的基本操作和理解

顺序表的理解操作:点击打开链接

单链表:一种链式存储的线性表,用一组地址任意的存储单元存放线性表的数据元素,称存储单元为一个节点。(每个结点中只包含一个指针域)
链式的存储结构的特点:用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)

单链表的结构:
           1.对于任意一个数据元素a(i)来说,储存本身的数据.(这个域叫数据域)
           2.存储一个下一个(后继)数据元素的信息(pNext)(这个域叫指针域)


这两部分信息组成数据元素a(i)的存储映像,称为结点。


单链表的结构:
typedef int DataType;

typedef struct SNode
{
	DataType data;       //保存本身的信息
	struct SNode *_pNext;//保存下个节点的地址

}SNode, *PNode;
代码部分:
list.h

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


typedef int DataType;

typedef struct SNode
{
	DataType data;       //保存本身的信息
	struct SNode *_pNext;//保存下个节点的地址

}SNode, *PNode;


void SListInit(PNode* pHead);// 链表的初始化 
void SListPushBack(PNode* pHead, DataType data);// 尾插 
void SListPopBack(PNode* pHead);// 尾删 
void SListPushFront(PNode* pHead, DataType data);// 头插 
void SListPopFront(PNode* pHead);// 头删 
PNode SListFind(PNode pHead, DataType data);// 在链表中查找值为data的元素,找到后返回值为data的结点
void SListInsert(PNode* pHead, PNode pos, DataType data);// 在pos位置插入值为data的结点 
void SListErase(PNode* pHead, PNode pos);// 删除pos位置的结点 
int SListSize(PNode pHead);// 获取链表中节点总数
int SListEmpty(PNode pHead);// 判断链表是否为空 
void SListDestroy(PNode* pHead);// 销毁链表
void PrintfList(PNode pHead);//打印链表


list.c

#include "list.h"

//初始化就是将链表头指针赋空,
//注意这里要传头指针的地址才能改变头指针的值
void SListInit(PNode* pHead)
{
	assert(pHead);//判断链表是否存在
	*pHead = NULL;
}
//创建新节点
PNode BuyNewNode(DataType data)
{
	PNode ptr = NULL;
	ptr = (PNode)malloc(sizeof(DataType)+sizeof(PNode));

	if (NULL == ptr)
	{
		printf("BuyNewNode failed!!!\n");
		return NULL;
	}
	//申请成功  
	ptr->data = data;
	ptr->_pNext = NULL;
	return ptr;
}

//打印链表
void PrintfList(PNode pHead)
{
	PNode ptr = pHead;
	if (pHead == NULL)
		return;
	while (ptr)
	{
		printf("%d-->", ptr->data);
		ptr = ptr->_pNext;
	}
	printf("NULL\n");

}

//尾插
void SListPushBack(PNode* pHead, DataType data)
{
	PNode pCur = NULL;
	assert(pHead);//判断链表是否存在

	if (*pHead == NULL)//判断链表是否为空
	{
		*pHead = BuyNewNode(data);//空就让头节点指向新节点
		return;
	}

	//1.先找到链表最后一个节点
	pCur = *pHead;
	while (pCur->_pNext)
	{
		pCur = pCur->_pNext;//朝后走一步
	}
	pCur->_pNext = BuyNewNode(data);

}

//尾删
void SListPopBack(PNode* pHead)
{
	assert(pHead);
	PNode pPre = *pHead;
	PNode pCur = *pHead;

	if (*pHead == NULL)
	{
		printf("链表已空,删除失败!!!\n");
		return;
	}

	//1.只有一个节点
	if (pCur->_pNext == NULL)
	{
		free(*pHead);
		*pHead = NULL;
		return;
	}
	//2.有一个以上节点
	while (pCur->_pNext)
	{
		pPre = pCur;//因为要找到倒数第二个节点,所以每走一步之前先保存
		pCur = pCur->_pNext;
	}
	free(pPre->_pNext);
	pPre->_pNext = NULL;
}

//头插
void SListPushFront(PNode* pHead, DataType data)
{
	PNode ptr = NULL;
	assert(pHead);
	//1.链表为空
	if (NULL == *pHead)
	{
		*pHead = BuyNewNode(data);
		return;
	}

	//2.链表不为空
	ptr = *pHead;//先保存第一个节点地址
	*pHead = BuyNewNode(data);//头指针指向新节点
	(*pHead)->_pNext = ptr;//新节点的_pNext指向原来的头节点

}

//头删
void SListPopFront(PNode* pHead)// 头删
{
	assert(pHead);
	PNode ptr = NULL;
	if (NULL == pHead)
	{
		printf("链表已空,删除失败!!!\n");
		return;
	}

	//1.只有一个节点
	if ((*pHead)->_pNext == NULL)
	{
		free(*pHead);
		*pHead = NULL;
		return;
	}

	//2.有一个以上的节点
	ptr = *pHead;//先保存头节点地址
	*pHead = (*pHead)->_pNext;//头指针朝后走一步;
	free(ptr);//释放原头节点空间
}
//查找为data的节点
PNode SListFind(PNode pHead, DataType data)
{
	PNode ptr = pHead;
	if (NULL == pHead)
	{
		printf("对不起,为空链表!!!\n");
		return NULL;
	}

	while ((ptr) && (ptr->data != data))//ptr中的data不是要找的且不为空就进入循环
	{
		ptr = ptr->_pNext;
	}

	//1.ptr为空,证明找不到
	if (NULL == ptr)
	{
		printf("对不起,找不到!!!\n");
		return NULL;
	}
	else
		return ptr;
}

int SListSize(PNode pHead)
{
	int count = 0;
	while (pHead)
	{
		pHead = pHead->_pNext;
		count++;
	}
	return count;
}

void SListInsert(PNode* pHead, PNode pos, DataType data)
{
	assert(pHead);

	//1.链表为空
	if (NULL == *pHead)
	{
		//1.如果链表为空,插入位置与头节点地址不相同,那么位置不合法
		if (pos == *pHead)
		{
			*pHead = BuyNewNode(data);
			return;
		}
		else
		{
			printf("位置不合法,插入失败!!!\n");
			return;
		}
	}

	//2.链表不为空
	//(1)头插:pos与头节点地址相等
	if (pos == *pHead)
		SListPushFront(pHead, data);
	//(2)pos与头节点位置不相等
	else
	{
		PNode pPre = *pHead;
		PNode pCur = *pHead;
		while ((pCur) && (pCur->_pNext != pos))
		{
			pCur = pCur->_pNext;
		}
		if (pCur == NULL)
		{
			printf("对不起,找不到该节点!!!\n");
			return;
		}
		else
		{
			pCur->_pNext = BuyNewNode(data);//插入新节点
			pCur->_pNext->_pNext = pos;//新节点链接pos处的节点
			pos = pCur->_pNext;//pos指向新节点
		}

	}
}


// 删除pos位置的结点 
void SListErase(PNode* pHead, PNode pos)
{
	assert(pHead);
	PNode ptr = *pHead;

	if (NULL == *pHead)
	{
		printf("链表已空,删除失败!!!\n");
		return;
	}

	//1.只有一个节点
	if ((*pHead)->_pNext == NULL)
	{
		if (*pHead == pos)
		{
			free(pos);
			*pHead = NULL;
			return;
		}

		else
		{
			printf("位置不合法,删除失败!!!\n");
			return;
		}
	}

	//2.有一个以上节点
	//(1)如果pos是头节点
	if (pos == *pHead)
	{
		*pHead = (*pHead)->_pNext;
		free(pos);
		return;
	}

	//(2)不是头结点
	while ((ptr) && (ptr->_pNext != pos) && (pos))
	{
		ptr = ptr->_pNext;
	}

	if ((ptr == NULL) || (pos == NULL))
	{
		printf("节点不存在,删除失败!!!\n");
		return;
	}
	else
	{
		ptr->_pNext = pos->_pNext;//链接起pos的下个节点
		free(pos);
	}
}
// 判断链表是否为空 
int SListEmpty(PNode pHead)
{
	if (pHead)
		return 1;
	return 0;
}

// 销毁链表
void SListDestroy(PNode* pHead)
{
	assert(pHead);
	PNode ptr = *pHead;
	PNode pMsg = *pHead;

	while (ptr)
	{
		ptr = ptr->_pNext;//ptr朝后走
		free(pMsg);//释放pMsg指向的空间

		if (ptr)
			pMsg = ptr;//pMsg跟着ptr走
	}
	*pHead = NULL;
}

test.c

#include <windows.h>

void TestList()
{

	SNode SList;
	PNode pHead = &SList;
	SListInit(&pHead);// 链表的初始化
	//SListEmpty(pHead);// 判断链表是否为空 
	//SListInsert(&pHead, pHead, 40);
	//PrintfList(pHead);
	//SListPushFront(&pHead, 0);
	//PrintfList(pHead);
	SListPushBack(&pHead, 5);//尾插
	SListPushBack(&pHead, 10);
	SListPushBack(&pHead, 3);
	PrintfList(pHead);
	//SListPopBack(&pHead);//尾删
	//PrintfList(pHead);
	//SListPushFront(&pHead, 0);//头插
	////PrintfList(pHead);
	////SListPopFront(&pHead);//头删
	//PrintfList(pHead);
	//// 在链表中查找值为data的元素,找到后返回值为data的结点
	//SListFind(pHead, 3);
	//SListSize(pHead);// 获取链表中节点总数
	//SListInsert(&pHead, pHead->_pNext->_pNext, 20);// 在pos位置插入值为data的结点 
	//PrintfList(pHead);
	//SListErase(&pHead, pHead->_pNext->_pNext);// 删除pos位置的结点
	//PrintfList(pHead);
	//SListDestroy(&pHead);// 销毁链表

}
int main()
{


	TestList();
	

	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/alidada_blog/article/details/80412723
今日推荐