C,C++单链表基本操作的实现

单链表的定义和表示
对于每一个数据元素 a1,除了要存储本身信息外,还要存储下一个数据元素的地址。这里就要用到结构指针。这两部分信息组成的数据元素 a1 的存储映像,称为结点,存储信息的域称为数据域;存储直接后继存储位置的称为指针域。指针域中存储的信息称作指针。n 个结点的链结成一个链表,即为线性表
特点:用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)。

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

一.初始化
1.生成新结点作为头结点,用头指针L指向头结点。
2.头结点的指针域置空。

Status InitList(LinkList &L) 
{//构造一个空的单链表L
	L = new LNide;				//生成新结点作为头结点,用头指针L指向头结点
	L->next = NULL;				//头结点的指针域置空 
	return OK; 
}

二.取值
1.用指针p指向首元结点,用 j 做计数器初值赋为 1 。
2.从首元结点开始依次顺着链域 next 向下访问,只要指向当前节点的指针 p 不为空(NULL),并且没有到达序号为 i 的结点,则循环执行以下操作。
a. p 指向下一个节点;
b, 计数器 j 相应加 1 。
c. 退出循环时,如果指针 p 为空,或者计数器 j 大于 i,说明指定的序号 i 值不合法(i 大于表长 n 或 i 小于等于 0),取值失败返回ERROR;否则取值成功,此时 j = i时, p 所指的结点就是要找的第 i 个结点用参数 e 保存当前结点的数据域,返回OK。

Status GetElem(LinkList L, int i, ElemType &e)
{//带头节点的单链表L中根据序号i获取元素的值,用e返回L中第i个数据元素的值 
	p = L->next ;
	j = 1;									//初始化,p指向首元结点,计数器j初值赋为1
	while(p && j < i) 						//顺链域向后扫描,直到 p 为空或 p 指向第 i 个元素 
	{
		p = p->next;						// p 指向下一个结点; 
		++j;								//计数器 j 相应加 1; 
	}
	if(!p || j > 1) return ERROR;			//i 值不合法 i > n 或 i <= 0 
	e = p->data;							//取第 i 个结点的数据域 
	return OK; 
}

三.查找
1.用指针 p 指向首元结点。
2.从首元结点开始依次顺着链域 next 向下查找,只要指向当前节点的指针 p 不为空,并且 p 所指向的数据域不等于给定值 e ,则循环执行以下操作:p 指向下一个结点。
3.返回 p 。若查找成功,p 此时即为结点的地址值,若查找失败,p 的值即为NULL。

LNode *LocateElem (LinkList L, ElemType e)
{//在带头节点的单链表L中查找值为e的元素 
	p = L->next;					//初始化,p指向首元结点
	while(p && p->data != e) 		//链域向后扫描,直到p为空或p所指向结点数据域等于e
		p = p->next;				//p指向下一个结点 
	return p; 						//查找成功弄返回值为e的结点地址p,查找失败返回NULL 
}

四.插入
1.查找结点 a(i-1),并由指针 p 指向该结点。
2.生成一个新的结点 *s。
3.将新结点 *s 的数据域置为e.
4.将新结点 *s 的指针域指向结点 ai。
5.将结点 *p 的指针域指向新结点 *s。

Status ListInsert(LinkList &L, int i, ElemType e) 
{//在带头节点的单链表L中 第i个位置插入值为e的新结点
	p = L;
	j = 0;
	while(p && (j < i - 1)) 
	{									//查找第i - 1个结点,p指向该节点 
		p = p->next;					
		++j;					
	} 
	if(!p || j > i - 1) return ERROR;	//i > n + 1 或者 i < 1 
	s = new LNode;						//生成新结点*s 
	s->data = e;						//将结点*s的数据域置为e 
	s->next = p->next;					//将结点*s的指针域指向结点a
	p->next = a;						//将结点*p的指针域指向结点*s 
	return OK; 
}	

五.删除
1.查找结点 a(i-1),并由指针 p 指向该结点。
2.临时保存待删除结点 ai 的地址在 q 中,以备释放。
3.将结点*p的指针域指向 ai 的直接后继结点。
4.释放结点 ai 的空间。

Status ListDelete(LinkList &L, int i, ElemType e) 
{//在带头节点的单链表L中 删除第i个元素 
	p = L;
	j = 0;
	while(p->next && (j < i - 1)) 
	{											//查找第i - 1个结点,p指向该节点 
		p = p->next;					
		++j;					
	} 
	if(!(p->next) || j > i - 1) return ERROR;	//i > n 或者 i < 1 ,删除位置不合理 
	q = p->next;								//生成新结点*s 
	p->next = q->next;							//临时保存待删除结点的地址,以备释放。
	s->next = p->next;							//改变删除结点前驱结点的指针域
	delete q;									//释放删除结点的空间。
	return OK; 
}

六.创建单链表(前插法)
1.创建一个只有头结点的空链表。
2.根据待创建链表包括的元素个数 n ,循环 n 次执行以下操作:
a.生成一个新结点 *p。
b.输入元素值赋给新结点 *p 的数据域。
c.将新结点 *p 插入到头结点之后。

void CreatList_H(LinkList &L, int n) 
{//逆位序输入n个元素的值,建立带表头结点的单链表L; 
	L = new LNode;
	L->next  = NULL;						//先建立一个带头结点的空链表 
	for(i = 0; i < n; ++i)
	{
		p = new  LNode;						//生成新结点*p 
		cin>>p->data;						//输入元素值赋给新结点 *p 的数据域。
		p->next = L->next;L->next = p;		//将新结点 *p 插入到头结点之后。
	}
}

七.创建单链表(后插法)
1.创建一个只有头结点的空链表。
2.尾指针 r 初始化,指向头结点。
3.根据待创建链表包括的元素个数 n ,循环 n 次执行以下操作:
a.生成一个新结点 *p。
b.输入元素值赋给新结点 *p 的数据域。
c.将新结点 *p 插入到尾结点 *r 之后。
d.尾指针 r 指向新的尾结点 *p。

void CreatList_R(LinkList &L, int n) 
{//正位序输入n个元素的值,建立带表头结点的单链表L; 
	L = new LNode;
	L->next  = NULL;						//先建立一个带头结点的空链表 
	r = L; 									//尾指针 r 初始化,指向头结点。
	for(i = 0; i < n; ++i)
	{
		p = new  LNode;						//生成新结点*p 
		cin>>p->data;						//输入元素值赋给新结点 *p 的数据域。
		p->next = NULL; r->next = p;		//将新结点 *p 插入到尾结点 *r 之后。
		r = p;								//尾指针 r 指向新的尾结点 *p。
	}
}

文章借鉴:《数据结构》(C语言版)(第二版)人民邮电出版社

发布了11 篇原创文章 · 获赞 22 · 访问量 6496

猜你喜欢

转载自blog.csdn.net/m0_46168903/article/details/104054285