数据结构学习笔记||单链表

单链表

插入和删除结点的操作

1)插入结点
在单链表中插入一个新结点需要找到插入后的前驱结点
在这里插入图片描述
代码描述:

s->next=p->next;
p->next=s;

2)删除结点
需要找到其前驱结点
在这里插入图片描述
代码描述

p->next=p->next->next

一般情况下,删除结点后还需要释放其内存空间

q=p->next;               //q临时保存被删结点
p->next=q->next;        //从链表中删除结点q
free(q);                //释放结点q的空间

单链表基本运算

#include<stdio.h>
#include<malloc.h>
typedef int ElemType;
typedef struct LNode
{
	ElemType data;            //存放元素值
	struct LNode *next;       //指向后继结点 
} LinkNode;                   //单链表结点类型

//头插法:从一个空表开始依次读取数组a中的元素,生成一个新结点(由s指向它),
//将读取的数组元素存放到该结点的数据域中,再将其插入到当前链表的表头上(即头结点之后)
void CreateListF(LinkNode *&L,ElemType a[],int n)
{
	LinkNode *s;
	L=(LinkNode *)malloc(sizeof(LinkNode));
	L->next=NULL;               //创建头结点,其next域置为NULL
	for(int i=0;i<n;i++)        //循环建立数据结点s
	{
		s=(LinkNode *)malloc(sizeof(LinkNode));
		s->data=a[i];           //创建数据结点s
		s->next=L->next;        //将结点s插入到原首结点之前、头结点之后
		L->next=s; 
	} 
}

//尾插法:从一个空表开始依次读取数组a中的元素,生成一个新结点s,将读取的数组元素
//存放到该结点的数据域中,再将其插入到当前链表的表尾上
void CreateListR(LinkNode *&L,ElemType a[],int n)
{
	LinkNode *s,*r;
	L=(LinkNode *)malloc(sizeof(LinkNode));    //创建头结点
	r=L;                                      //r始终指向尾结点,初始时指向头结点
	for(int i=0;i<n;i++)                     //循环建立数据结点
	{
		s=(LinkNode *)malloc(sizeof(LinkNode));
		s->data=a[i];                         //创建数据结点s
		r->next=s;                            //将结点s插入结点r之后
		r=s; 
	} 
	r->next=NULL;                            //尾结点的next域置为NULL 
}

//初始化线性表:建立一个空的单链表
void InitList(LinkNode *&L)
{
	L=(LinkNode *)malloc(sizeof(LinkNode));
	L->next=NULL;                  //创建头结点,其next置域为NULL 
}

//销毁线性表:释放单链表L占用的内存空间,即逐一释放全部结点的空间
//让pre、p指向两个相邻的结点(初始时pre指向头结点,p指向首结点)
void DestroyList(LinkNode *&L)
{
	LinkNode *pre=L,*p=L->next;               //pre指向结点p的前驱结点
	while(p!=NULL)                            //扫描单链表L
	{
		free(pre);                           //释放pre结点
		pre=p;                               //pre、p同步后移一个结点
		p=pre->next;                            
	}
	free(pre);                              //循环结束时p为NULL,pre指向尾结点,释放它 
}

//判断线性表是否为空表:单链表L中没有数据结点时返回真,否者返回假
bool ListEmpty(LinkNode *L)
{
	return(L->next==NULL);
}

//求线性表的长度:返回单链表L中数据结点的个数
//让P指向头结点,n用来累计数据结点个数(初始值为0)
//当p不为空时循环:n增1,p指向下一个结点。循环结束后返回n。
int ListLength(LinkNode *L)
{
	int n=0;
	LinkNode *p=L;                  //p指向头结点,n置为0(即头结点的序号为0)
	while(p->next!=NULL)
	{
		n++;
		p=p->next;
	}
	return(n);                    //循环结束,p指向尾结点,其序号n为结点个数 
}

//输出线性表:逐一扫描单链表L的每个数据结点,并显示各结点的data域置
void DispList(LinkNode *L)
{
	LinkNode *p=L->next;          //p指向首结点
	while(p!=NULL)                //p不为NULL,输出p结点的data域
	{
		printf("%d",p->data);
		p=p->next;               //p移向下一个结点 
	}
	printf("\n"); 
}

//求线性表中的某个数据元素值:在单链表L中从头开始找到第i个结点,若存在第i个数据结点,
//则将其data域值赋给变量e
//让p指向头结点,j用来累计遍历过的数据结点个数(初始值为0),当j<i且p不为空时循环: 
//j增1,p指向下一个结点。循环结束后有两种情况,若p为空,表示单链表L中没有第i个数据
//结点(参数i错误),返回false;否则找到,提取值并返回true
bool GetElem(LinkNode *L,int i,ElemType &e)
{
	int j=0;
	LinkNode *p=L;               //p指向头结点,j置为0(即头结点的序号为0)
	if(i<=0)return false;        //i值错误返回假
	while(j<i&&p!=NULL)          //找第i个结点p
	{
		j++;
		p=p->next;
	}
	if(p==NULL)                //不存在第i个数据结点,返回false
	   return false;
	else                      //存在第i个数据结点,返回true
	{
		e=p->data;
		return true;
	} 	 
}

//按元素值查找:在单链表L中从头开始找第一个值域与e相等的结点,若存在这样的结点,
//则返回逻辑序号,否则返回0 
int LocateElem(LinkNode *L,ElemType e)
{
	int i=1;
	LinkNode *p=L->next;         //p指向首结点,i置为1(即首结点的序号为1)
	while(p!=NULL&&p->data!=e)   //查找data值为e的结点,其序号为i
	{
		p=p->next;
		i++;
	}
	if(p==NULL)                   //不存在值为e的结点,返回0
	  return(0);
	else                          //存在值为e的结点,返回其逻辑序号i 
	  return(i); 
}

//插入数据元素:先在单链表L中找到第i-1个结点,由p指向它
//若存在这样的结点,将值为e的结点(s指向它)插入到p所指结点的后面
bool ListInsert(LinkNode *&L,int i,ElemType e)
{
	int j=0;
	LinkNode *p=L,*s;             //p指向头结点,j置为0(即头结点的序号为0)
	if(i<=0)return false;         //i错误返回false
	while(j<i-1&&p!=NULL)         //查找第i-1个结点p
	{
		j++;
		p=p->next;
	}
	if(p==NULL)                   //未找到第i-1个结点,返回false
	 return false;
	else                         //找到第i-1个结点p,插入新结点并返回true 
	{
		s=(LinkNode *)malloc(sizeof(LinkNode));
		s->data=e;               //创建新结点s,其data域置为e
		s->next=p->next;         //将结点s插入到结点p之后
		p->next=s;
		return true; 
	} 
}

//删除数据元素:先在单链表L中找到第i-1个结点,由p指向它。
//若存在这样的结点,且也存在后继结点(由q指向它),则删除q所指的结点,返回true
//否则返回false,表示参数i错误
bool ListDelete(LinkNode *&L,int i,ElemType &e)
{
	int j=0;
	LinkNode *p=L,*q;          //p指向头结点,j置为0(即头结点的序号为0)
	if(i<=0)return false;      //i错误返回false
	while(j<i-1&&p!=NULL)      //查找第i-1个结点
	{
		j++;
		p=p->next;
	}
	if(p==NULL)               //未找到第i-1个结点,返回false
	  return false;
	else                     //找到第i-1个结点p 
	{
		q=p->next;          //q指向第i个结点
		if(q==NULL)         //若不存在第i个结点,返回false
		  return false;
		e=q->data;
		p->next=q->next;    //从单链表中删除q结点
		free(q);            //释放q结点
		return true;        //返回true表示成功删除第i个结点                 
	}  
}
 
 
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值