数据结构模板之二:单链表

①基本定义

线性表是具有相同特征的数据结构元素的一个有限序列。

链表即线性表的链式存储结构,与顺序表相比,链表可以实现存储空间的动态管理,而顺序表必须事先分配一整块的存储空间,这样会降低存储空间的利用率。


②存储方式与结构

线性表(a1,a2,...,an-1,an)

↓映射

链表


链表中每个结点都含有一个指针,用于指向后继结点。通常每个链表都含有一个头结点,并通过头结点的指针指向该链表,注意:头结点不存储数据,只含一个指向链表的指针,尾结点中的指针不需要指向其他任何结点,则置为空(NULL),值得一提的是,若尾结点的指针又指向了头结点,那么这个单链表就成了循环链表。


③实现

#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;
typedef struct LNode
{
	ElemType data;
	struct LNode *next;
}LinkNode;

/*****建立单链表(头插法)*****/
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;
	}
}

/*****建立单链表(尾插法)*****/
void CreateListR(LinkNode * &L,ElemType a[],int n)
{
	LinkNode *s,*r;
	L=(LinkNode *)malloc(sizeof(LinkNode));         //创建头结点
	r=L;                                            //r始终指向尾结点,初始时指向头结点
	for(int i;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
}

/*****销毁线性表*****/
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指向尾结点,释放它
}

/*****判断线性表是否为空表*****/
bool ListEmpty(LinkNode *L)
{
	return (L->next==NULL);
}

/*****求线性表的长度*****/
int ListLength(LinkNode *L)
{
	int n=0;
	LinkNode *p=L;                //p指向头结点,n置为0,(即头结点的序号为0)
	while(p->next !=NULL)
	{
		n++;
		p->next;
	}
	return n;                    //循环结束,p指向尾结点,其序号n为结点个数
}

/*****输出线性表*****/
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");
}

/*****求线性表中的某个数据元素值*****/
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个结点
	{
		j++;
		p->next;
	}
	if(p==NULL)                              //不存在第i个元素结点,返回false
		return false;
	else
	{
		e=p->data;
		return true;
	}
}

/*****按元素值查找*****/
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的结点,返回其逻辑序号i
		return 0;
	else 
		return (i);
}

/*****插入数据元素*****/
bool ListInsert(LinkNode * &L,int i,ElemType e)
{
	int j=0;
	LinkNode *p=L,*s;                           //p指向头结点,j置为0,(即头结点序号为0)
	if(i<=0)
		return false;                           //错误返回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;
	}
}

/*****删除数据元素*****/
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个结点
	{
		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个结点
	}
}

int main()
{
	return 0;
}

注:建立单链表可采用头插法或尾插法,头插法将每一次插入的数据排在第一位,也就是说,使用头插法创建的链表和原先线性表中的数据的顺序是相反的,所以说,若非特殊情况需要倒置线性表,我们一般采用尾插法创建链表。

---代码和部分内容参考自《数据结构教程》

猜你喜欢

转载自blog.csdn.net/Gsdxiaohei/article/details/80791217