单向链表的实现

单链表的建立、头插、尾插、给定位置插入、尾删、给定位置删除、节点的查找、链表的销毁:

#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<stdlib.h>
typedef int DataType; 
//pHead:头结点 ppHead:指向pHead的指针 *ppHead:存放的是pHead指向的地址
typedef struct SListNode 
{ 
struct SListNode* _next; 
DataType _data; 
}SListNode; 


SListNode* BuySListNode(DataType x)
{
	SListNode* node=(SListNode*)malloc(sizeof(SListNode)*1);//创建一个结构体指针指向开辟的结构体空间
	node->_next=NULL;//通过指针访问内部成员,将_next指针指向地址置空
	node->_data=x;//同理
	return node;//返回指针
}
void SListPrint(SListNode* pHead)//链表的打印
{
	//assert(pHead);//判断头结点指针内部地址是否为空,是就进
    SListNode* node=pHead;
	while(node!=NULL)
	{
		 printf("%d\n",node->_data);
      node=node->_next;//通过指针访问内部成员,(判断第一个节点的下一个地址是否为空,是否存在下一节点)将pHead指向下一个节点
	}
}
void SListDestory(SListNode** ppHead)//链表的销毁
{
	 assert(*ppHead);//判断链表是否为空
	 SListNode* node=*ppHead;//node指向第一个节点
      SListNode* noode=NULL;//建立noode指针
	 while(node)//进行循环遍历节点,并销毁
	 {
         noode=node->_next;;//令noode指向当前节点的下一个节点
		 free(node);//销毁当前节点空间
		 node=noode;//将下一节点的地址给node并进入循环判断条件
	 }
      *ppHead=NULL;//销毁完成,将头指针置空

}

void SListPushBack(SListNode** ppHead, DataType x)//尾部压入(建立二级指针,指向pHead)
{
      SListNode* newnode=*ppHead;//建立指针指向第一个节点
	if(*ppHead==NULL)//判断是否为空链表,1.空链表
	{
      SListNode* Node= BuySListNode(x);//建立一个新节点,并使node指向它
	  *ppHead=Node;//使得头指针指向新建立的节点
	  (*ppHead)->_next=NULL;//节点的_next置空
	}
	else//2.非空链表
	{
	while(newnode->_next!=NULL)//循环找尾
	{  
		newnode=newnode->_next;//当循环进入最后一次时,newnode表示的是最后一个节点
	}
	SListNode* Node= BuySListNode(x);//建立新的节点
	Node->_next=NULL;//新节点的next指针置空
    newnode->_next=Node;//将Node指向的节点的地址给当前节点的_next
}
}
void SListPopBack(SListNode** ppHead)//尾删
{
  assert(*ppHead);//判断第一个节点是否存在
  SListNode *parent=NULL;
  SListNode *newnode=*ppHead;
  if(newnode->_next==NULL)//1.如果只有一个节点
  {
	  free(newnode);//删除节点
	  //newnode=NULL;
	 *ppHead=NULL;//头指针置空

  }
  else//2.若果存在多个节点
  {
  while(newnode->_next!=NULL)//判断节点地址是否为空,空表示没有节点,非空表示存在节点
  {
 	  parent=newnode;//parent指向前一个节点
	  newnode=newnode->_next;//newnode指向当前节点
  }
  free(newnode);//销毁尾节点
  parent->_next=NULL;//前一节点的next指针置空
  }

}
void SListPushFront(SListNode** ppHead, DataType x)//头插
{
 if(*ppHead==NULL)//1.空链表
 {
    SListNode* node= BuySListNode(x);//通过指针保存新节点的地址
	*ppHead=node;//头指针由指空变为指向新节点的地址
	(*ppHead)->_next=NULL;//将新节点的指向下一个节点的next指针指空
 }
 else//2.非空链表
 {
      SListNode* newnode= BuySListNode(x);//买一个新节点,并将它的新地址给newnode指针
    SListNode* next=*ppHead;//将第一个节点的地址给next
	*ppHead=newnode;//头指针指向新节点的地址
	newnode->_next=next;//将未插入之前的头结点的地址,给新节点的next指针
 }
}
SListNode* SListFind(SListNode* pHead, DataType x)//数据查找
{
	assert(pHead);//判断链表是否为空
	while(pHead)//通过循环条件来控制指针的走向,终止条件是指针指向空
	{
     if(pHead->_data==x)//如果指针指向的节点的数据等于x,就返回pHead
	 {
		 return pHead;
	 }
	 pHead=pHead->_next;//让指针指向下一个节点
	}
  return NULL;//如果跳出while循环,表示没有找到,返回NULL
}
void SListInsest(SListNode** ppHead, int pos, DataType x)//指定位置插入
{
     if(*ppHead==NULL)//1.链表为空
	 {
		 if(pos==1)//如果插入位置为一,合法
		 {
      SListNode* node=BuySListNode(x);
	  *ppHead=node;
		 }
		 else
			 printf("链表为空,找不到插入位置!\n");
	 }
	 else//2.链表不为空
	 {
		 int count=0;
         SListNode* Newnode=*ppHead;
		 while(Newnode)//通过循环计算链表的节点个数
		 {
			 count++;
			 Newnode=Newnode->_next;
		 }
		 if(pos>1&&pos<=count)//判断插入位置的范围,1.插入位置在中间
		 {
			    SListNode* parent=NULL;
                SListNode* NEWnode=*ppHead;
			 while(--pos)//进行循环,找到插入位置
			 {
              parent=NEWnode;//指向前一节点
              NEWnode=NEWnode->_next;//指向当前节点
			 }
			  SListNode* node=BuySListNode(x);
			  node->_next=parent->_next;//新节点的next指针指向未插入之前的当前节点的地址
			  parent->_next=node;//前一节点的next指针指向新节点
			  
		 }
		 if(pos==1)//2.插入位置在头部
		 {
             SListNode* newnode=*ppHead;
             SListNode* node=BuySListNode(x);
			 node->_next=newnode;//新节点的next指针指向未插入之前的第一个节点
			 *ppHead=node;//头指针指向新节点
			 
		 }
		 if(pos==count+1)//3.插入位置在尾部
		 {
			 SListNode* parent=NULL;
             SListNode* NEWNode=*ppHead; 
            while(NEWNode)//循环找尾
			 {
              parent=NEWNode;//当前节点
              NEWNode=NEWNode->_next;//下一节点
			 }
             SListNode* node=BuySListNode(x);
			 parent->_next=node;//将尾节点的next指针指向新节点
			 
		 }
		 else if(pos<1||pos>(count+1))//4.插入位置不合法
		 {
			 printf("插入位置不合法");
		 }
	 }
}
void SListErase(SListNode** ppHead, int pos)//指定位置节点删除
{
  assert(*ppHead);
  
		 int count=0;
         SListNode* newnoDe=*ppHead;
		 while(newnoDe)//通过循环计算链表的节点个数
		 {
			 count++;
			 newnoDe=newnoDe->_next;
		 }
		 if(1<pos&&pos<count)//1.中间位置删除
		 {
              SListNode* newnnode=*ppHead;
 			 SListNode* parent=NULL;
		 while(--pos)//循环找删除点
		 {
			  parent=newnnode;//上一节点
			  newnnode=newnnode->_next;//当前节点
		 }
		 parent->_next=newnnode->_next;//将上一节点的next指针指向当前节点的下一个节点地址
		 free(newnnode);//销毁当前节点
		 newnnode=NULL;//指针置空
		   
		 }
		 if(pos==1)//2.删除第一个节点
		 {  
			 SListNode* nnewnode=*ppHead;
			 *ppHead=nnewnode->_next;//头指针指向第一个节点的next,
			 free(nnewnode);//销毁当前节点
			 nnewnode=NULL;//指针置空
		 }
		 if(pos==count)//3。删除尾节点
		 {
               SListNode* newwnode=*ppHead;
			   SListNode* parent=NULL;
			 while(--pos)//循环找点
			 {
			  parent=newwnode;//前一节点
			  newwnode=newwnode->_next;//当前节点
			 }
			 free(newwnode);//销毁当前节点
			 parent->_next=NULL;//上一节点的next置空
			 newwnode=NULL;//指针置空,防止野指针
			 
		 }
		 else if(pos<=0||pos>count)//4.删除位置不合法
		 {
			 printf("位置不合法!");
		 }
}
void text()
{
SListNode* pHead=NULL;
SListPushBack(&pHead,1);
SListPushBack(&pHead,2);
SListPushBack(&pHead,3);
SListPopBack(&pHead);
SListPopBack(&pHead);
SListPopBack(&pHead);
SListPushFront(&pHead,1);
SListPushFront(&pHead,2);
SListPushFront(&pHead,3);
SListErase(&pHead,3);
SListDestory(&pHead);
//int ret=SListFind(pHead,2)->_data;
//printf("2? %d\n",ret);
//SListInsest(&pHead,4,4);

SListPrint(pHead);

}
int main()
{
    text();
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值