【数据结构---1】不带头的单向非循环链表知识整理

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

链表是一种物理储存上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序来实现的
链表分为:1.单向,双向2.带头,不带头3.循环和非循环,组合起来总共八种

熟悉链表带头结点和不带头结点的区别?

使用头结点,则第1个位置的插入和删除都是对p—>next进行操作,而不用动p本身,而且减少了算法分支

代码示例:

Slist.h

typedef int SLTDatatype;

typedef struct SListNode
{
     
   SLTDatatype _data;  
   struct SListNode* _Next;
}Node,*PNode;

typedef struct SList 
{
     
    Node* _Head;
}SList;

void SListInit(SList* s);

void SListDestroy(SList* s);

Node* BuySListNode(SLTDatatype data);

void SListPushFront(SList* s,SLTDatatype data);

void SListPopFront(SList* s);

void SListPushBack(SList* s,SLTDatatype data);

void SListPopBack(SList* s);

Node* SListFind(SList* s,SLTDatatype data);

Node* SListFindPos(SList* s, SLTDatatype data);

void SListInsertAfter(PNode pos,SLTDatatype data);

void SListEraseAfter(PNode pos);

void SListRemove(SList* s, SLTDatatype data);

size_t SListSize(SList* s);

int SListEmpty(SList* s);

void SListClear(SList* s);

Test.c

#include"Slist.h"
#include
#include
#include 

//初始化操作
void SListInit(SList* s)
{
     
	 assert(s);
	 s->_Head = NULL;
}

//销毁
void SListDestroy(SList* s)
{
     
	 assert(s);
	 
	 while (s->_Head)
	 {
     
	 	  PNode pCur = s->_Head;
		  s->_Head = s->_Head->_Next;
		  free(pCur);
	 }
}

//创建新的节点
Node* BuySListNode(SLTDatatype data)
{
     
	 PNode node = (PNode*)malloc(sizeof(Node));//给新节点申请内存空间
	 assert(node);//检验申请的空间是否成功
	 node->_data = data;
	 node->_Next = NULL;//把相应的数据存到节点内
	 return node;
}

//头插
void SListPushFront(SList* s,SLTDatatype data)
{
     
	 assert(s);
	 PNode node=BuySListNode(data);
	 assert(node);
	 node->_Next = s->_Head;//顺序不能颠倒,否则会破坏链表结构丢失数据
	 s->_Head = node;
}

//头删
void SListPopFront(SList* s)
{
     
	 assert(s);
	 assert(s != NULL);
	 s->_Head = s->_Head->_Next;
}

//尾插
void SListPushBack(SList* s,SLTDatatype data)
{
     
	 assert(s);
	 PNode node = BuySListNode(data);
	 node->_Next = NULL;
	 PNode pCur = s->_Head;
	 while (pCur->_Next!=NULL)
	 {
     
		  pCur = pCur->_Next;
	 }
	 pCur->_Next = node;
}

//尾删
void SListPopBack(SList* s)
{
     
	 assert(s);
	 if (s->_Head->_Next == NULL)//只有一个节点
	 {
     
		  SListPopFront(&s);
	 }
	 PNode pCur = s->_Head;
	 while (pCur->_Next->_Next != NULL)//pcur的下一个节点的next指向空,说明pcur是倒数第二个
	 {
     
		  pCur = pCur->_Next;
	 }
	 free(pCur->_Next);
	 pCur->_Next = NULL;
}

//查找节点的位置
Node* SListFindPos(SList* s, SLTDatatype data)
{
     
	 assert(s);
	 assert(s->_Head != NULL);
	 PNode pCur = s->_Head;
	 if (data < 1)
	 {
     
		  return s->_Head;
	 }
	 for (int i = 0; i < data-1;++i)
	 {
     
		  pCur = pCur->_Next;
	 }
	 return pCur;
}

//在pos后面的位置插入
void SListInsertAfter(PNode pos,SLTDatatype data)
{
     
	  PNode node = BuySListNode(data);
	  node->_Next = pos->_Next;
	  pos->_Next = node;
}

//删除pos后的节点
void SListEraseAfter(PNode pos)
{
     
	 if (pos->_Next == NULL)
	 {
     
		return;
	 }
	 else
	 {
     
		PNode node = pos->_Next->_Next;
		free(pos->_Next);
		pos->_Next = node;
	 }
}

//移除值为data的节点
void SListRemove(SList* s, SLTDatatype data)
{
     
	 assert(s);
	 if (s->_Head == NULL)
	 {
     
		  return;
	 }
	 if (s->_Head->_Next == NULL)
	 {
     
		  free(s->_Head);
		  s->_Head = NULL;
	 }
	 else
	 {
     
		   PNode pCur = s->_Head;
		   while (pCur->_Next != NULL)
		   {
     
			    PNode pPre = pCur;//pPre记录的是pCur的上一个
			    pCur = pCur->_Next;
			    if (pCur->_data == data)
			    {
     
				     pPre->_Next = pCur->_Next;
				     free(pCur);
				     pCur = pPre;
			    }
		   }
	 }
}

// 获取链表中有效节点的个数 
size_t SListSize(SList* s)
{
     
	 if (s->_Head == NULL)
	 {
     
		  return 0;
	 }
	 else if (s->_Head->_Next == NULL)
	 {
     
		  return 1;
	 }
	 else
	 {
     
		  PNode pCur = s->_Head;
		  int count=0;
		  for (pCur; pCur!= NULL; pCur = pCur->_Next)
		  {
     
			    count++;
		  }
		  return count;
	 }
}

// 检测链表是否为空 
int SListEmpty(SList* s)
{
     
	 if (s->_Head == NULL)
	 {
     
		  return 0;
	 }
	 else return 1;
}

//打印节点
void SListPrint(SList* s)
{
     
	 assert(s);
	 if (s->_Head == NULL)
	 {
     
		  printf("NULL\n");
	 }
	 else
	 {
     
		  PNode pCur = s->_Head;
		  while (pCur != NULL)
		  {
     
			   printf("%d--->", pCur->_data);
			   pCur = pCur->_Next;
		  }
		  printf("NULL\n");
	 }
}

void TestSList()
{
     
	SList s;
	SListInit(&s);
	SListPushFront(&s,1);
	SListPushFront(&s,2);
	SListPushFront(&s,3);
	SListPushFront(&s,4);
	SListPushFront(&s,5);//头插测试
 
	SListPrint(&s);
 
  	SListPopFront(&s);
 	SListPopFront(&s);
	SListPopFront(&s);//头删测试
 
	SListPrint(&s);
 
	SListPushBack(&s, 0);
	SListPushBack(&s, 1);	
	SListPushBack(&s, 2);//尾插测试
 
	SListPrint(&s);
 
	SListPopBack(&s);
	SListPopBack(&s);
	SListPopBack(&s);//尾删测试

	SListPrint(&s);
 
	SListPushFront(&s, 0); 
	SListPushFront(&s, 5);
	SListPushFront(&s, 9);
	SListPrint(&s);
 
	printf("所查元素是第%d个\n",SListFind(&s,1));
 
	//目前链表9--->5--->0--->2--->1--->NULL
	//在第二个节点后面插入1
	SListInsertAfter(SListFindPos(&s,2), 1);
	SListPrint(&s);
	//目前链表9--->5--->1--->0--->2--->1--->NULL
	//在第5个节点后面插入1
	SListInsertAfter(SListFindPos(&s,5), 1);
	SListPrint(&s);
 
	SListEraseAfter(SListFindPos(&s, 3));//把第三个节点后面的删掉
	SListPrint(&s);
 
	SListRemove(&s,1);//删除掉值为1的所有节点
	SListPrint(&s);

	SListSize(&s);
	printf("有效节点的个数:%d \n", SListSize(&s));

	SListEmpty(&s);
	printf("%d\n", SListEmpty(&s));
	
	SListPrint(&s);

	SListSize(&s);
	printf("有效节点的个数:%d \n", SListSize(&s));
 
	SListDestroy(&s);
}

int main()
{
     
	 TestSList();
	 system("pause");
	 return 0;
}

【数据结构---1】不带头的单向非循环链表知识整理_第1张图片
在这里插入图片描述在这里插入图片描述

你可能感兴趣的:(数据结构,链表)