数据结构——链表(C语言)

本文详细介绍了单链表的基本概念及各种操作实现,包括初始化、取值、查找、插入、删除等,并给出了前后插法创建单链表的具体步骤。此外还简述了循环链表与双向链表的特点与操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单链表

注意

  1. 一般情况下,为了处理方便,在单链表的第一个结点之前附设一个结点,称为头结点。
  2. 首元结点是指链表中存储第一个数据元素的结点。
  3. 头结点是在首元结点之前附设的一个结点。
  4. 头指针是指向链表中第一个结点的指针,增加头结点后,无论链表是否为空,头指针都是指向头结点的非空指针。
    在这里插入图片描述

单链表存储结构

typedef struct LNode{
	ElemType data;
	struct LNode *next;
}LNode,*LinkList;	//ListList为指向结构体LNode的指针类型

单链表初始化

步骤:

  1. 创建头结点
  2. 头结点指向为空
Status InitList(LinkList & L){
	L=new LNode;
	L->next=NULL;
	return OK;
}

单链表取值

步骤:

  1. 创建一个结点指针指向首元结点
  2. 当指针指向不为空且不超出索引,指针后移
  3. 将得到的值赋值给引用变量e
Status GetElem(LinkList L,int i,ElemType &e){
	LinkList p=L->next;
	int j=1;
	while(p&&j<i){
		p=p->next;
		j++;
	}
	if(!p||j>i)
		return ERROR;
	e=p->data;
	return OK;
}

单链表的查找

步骤:

  1. 创建一个结点指针指向首元结点
  2. 当指针不为空且指针所值的值不满足条件,指针后移
  3. 将得到的结点地址返回 若没有将返回NULL
LNode *LocateELem(LinkList L,ElemType e){
	LinkList p=L->next;
	while(e&&p->data!=e)
		p=p->next;
	return p;
}

单链表的插入

步骤:

  1. 生成一个结点指针p,指向链表的头结点
  2. 寻找插入位置的前一个位置,当没有到达指定位置,指针后移
  3. 生成新结点s,插入在p之后
Status ListInsert(LinkList &L,int i,ElemType e){
	LinkList p=L;//指向头结点而不是首元结点,是因为有可能i为1,即链表首元结点
	int j=0;
	while(p&&j<i-1){//注意这里是i-1,因为插入的位置为i,前面有i-1个元素
		p=p->next;
		j++;
	}
	if(!p||j>i-1)
		return ERROR;
	LinkList s=new LNode;//插入p后面
	s->date=e;
	s->next=p->next;
	p->next=s;
	return OK;
}

单链表的删除

  1. 创建一个结点指针指向链表的首元结点
  2. 寻找删除结点的前一个元素,未到则指针不断后移
  3. 创建一个结点指针指向要删除的元素,以便内存释放
Status ListDelete(LinkList & L,int i){
	LinkList p=L->next;
	int j=0;
	while(p&&j<i-1)[//i-1是因为要找到删除结点的前一个结点
		p=p->next;
		j++;
	}
	if(!p||j>i-1)
		return ERROR;
	//p->next=p->next->next;按道理可以这样,但是删除结点的地址未被释放
	LinkList q=p->next;
	p->next=q->next;
	delete q;
	return OK;
}

创建单链表(前插法和后插法)

前插法步骤:

  1. 创建头结点
  2. 创建新结点,将其插到头结点之后(即新插入结点为链表的首元结点)
void CreateList_H(LinkList & L,int n){
	L=new LNode;
	L->next=NULL;
	LinkLNode p;
	for(int i=0;i<n;i++){
		p=new LNode;
		cin>>p->data;
		p->next=L->next;//将新结点插到头结点之后
		L->next=p;
	}
}

后插法步骤:

  1. 创建头结点
  2. 创建链表尾指针,指向头结点
  3. 将新结点插在尾结点之后,新结点称为尾结点
void CreateList_R(LinkList &L,int n){
	L=new LNode;
	L->next=NULL;
	LinkList r=L;//将链表尾结点指向头结点
	LinkLNode p;
	for(int i=0;i<n;i++){
		p=new LNode;
		cin>>p->data;
		p->next=NULL;
		r->next=p;
		r=p;
	}
}

循环链表

注意

  1. 循环链表中最后一个结点的指针域指向头结点
  2. 在某些情况下,若在循环链表中设立尾指针不设头指针,可以使操作简化(两个线性表合并可以将一方的尾指针指向另一方的第一个结点,然后释放其头结点
p=B->next->next;//B的头结点
B->next=A->next->next;//B尾结点指向A头结点
A->next=p;//A尾结点指向B头结点

在这里插入图片描述

双向链表

定义

在双向链表的结点中有两个指针域,一个指向直接后继,另一个指向直接前驱

存储结构

typedef struct DulNode{
	ElemType data;
	struct DulNode *prior;
	struct DulNode *next;
}DulNode,*DuLinkList;

结构特性

d->next->prior=d->prior->next=p;

双链表的插入

步骤:

  1. 寻找插入位置
  2. 建立新结点
  3. 进行指针修改,保证结点的不丢失

插在p之前,保证p的前项不丢失

Status ListInsert_DuL(DuLinkList &L,int i,ElemType e){
	if(!(p=GetElem_Dul(L,i)))//在L中确定第i个元素的指针
		return ERROE;
	DuLinkList s=new DuNode;
	s->data=e;
	s->prior=p->prior;
	p->prior->next=s;
	s->next=p;
	p->prior=s;
	return OK;
}
	

插在p之后,保证p的后项不丢失

Status ListInsert_DuL(DuLinkList &L,int i,ElemType e){
	DuListLink p=L;
	int j=0;
	while(p&&j<i-1){
		p=p->next;
		j++;
	}
	if(!p||j>i-1)
		return ERROR;
	DuListLink s=new DulNode;
	DulNode->data=e;
	s->next=p->next;
	p->next->prior=s;
	s->prior=p;
	p->next=s;
	return OK;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值