栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

数据结构——链表(c/c++)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

数据结构——链表(c/c++)

前言

本文仅作为学习笔记,如有错误和不足,欢迎大家指正。

1.顺序表 1.1顺序表的定义

顺序表可以看作为一个结构体,存放了一个数组和数组的长度。
顺序表定义:

typedef int ElemType; 
typedef struct 
{	ElemType data[MaxSize];		//存放顺序表元素
   	int length;					//存放顺序表的长度
} SqList;

1.2顺序表的基本用法

基本用法如下:

void CreateList(SqList *&L,ElemType a[],int n)
//建立顺序表
{
	L=(SqList *)malloc(sizeof(SqList));
	for (int i=0;idata[i]=a[i];
	L->length=n;
}
//初始化顺序表
void InitList(SqList *&L)
{
	L=(SqList *)malloc(sizeof(SqList));	//分配存放线性表的空间
	L->length=0;
}
//销毁顺序表
void DestroyList(SqList *&L)
{
	free(L);
}
//清空顺序表
bool ListEmpty(SqList *L)
{
	return(L->length==0);
}
//获取顺序表的长度
int ListLength(SqList *L)
{
	return(L->length);
}
//输出顺序表
void DispList(SqList *L)
{
	for (int i=0;ilength;i++)
		printf("%d ",L->data[i]);
	printf("n");
}
//获取顺序表的第i位的元素
bool GetElem(SqList *L,int i,ElemType &e)
{
	if (i<1 || i>L->length)
		return false;
	e=L->data[i-1];
	return true;
}
//获取元素在顺序表中的位置
int LocateElem(SqList *L, ElemType e)
{
	int i=0;
	while (ilength && L->data[i]!=e) i++;
	if (i>=L->length)
		return 0;
	else
		return i+1;
}
//插入元素
bool ListInsert(SqList *&L,int i,ElemType e)
{
	int j;
	if (i<1 || i>L->length+1)
		return false;
	i--;						//将顺序表位序转化为elem下标
	for (j=L->length;j>i;j--) 	//将data[i]及后面元素后移一个位置
		L->data[j]=L->data[j-1];
	L->data[i]=e;
	L->length++;				//顺序表长度增1
	return true;
}
//删除元素
bool ListDelete(SqList *&L,int i,ElemType &e)
{
	int j;
	if (i<1 || i>L->length)
		return false;
	i--;						//将顺序表位序转化为elem下标
	e=L->data[i];
	for (j=i;jlength-1;j++)	//将data[i]之后的元素前移一个位置
		L->data[j]=L->data[j+1];
	L->length--;				//顺序表长度减1
	return true;
}

2.单链表 2.1单链表的定义

定义单链表:

typedef int ElemType;
typedef struct LNode  
{
	ElemType data;
	struct LNode *next;		//指向后继结点
} linkNode;

基于单链表的结构,单链表具有以下特性:
当访问过一个节点过后,只能接着访问它的后继节点,而无法访问它的前驱节点。(单链表的指针指前不指后)

链表非常像火车,一个节点单向连接另一个节点,头节点就像是火车头,正如俗语所诉:“火车跑的快,全靠车头带”。
使用头节点的好处是:

基于以上优点,单链表、双链表、部分循环链表都使用了头节点。

2.2单链表的基本用法

单链表基本用法如下:

void CreateListF(linkNode *&L,ElemType a[],int n)
//头插法建立单链表
{
	linkNode *s;
	L=(linkNode *)malloc(sizeof(linkNode));  	//创建头结点
	L->next=NULL;
	for (int i=0;idata=a[i];
		s->next=L->next;			//将结点s插在原开始结点之前,头结点之后
		L->next=s;
	}
}
void CreateListR(linkNode *&L,ElemType a[],int n)
//尾插法建立单链表
{
	linkNode *s,*r;
	L=(linkNode *)malloc(sizeof(linkNode));  	//创建头结点
	L->next=NULL;
	r=L;					//r始终指向终端结点,开始时指向头结点
	for (int i=0;idata=a[i];
		r->next=s;			//将结点s插入结点r之后
		r=s;
	}
	r->next=NULL;			//终端结点next域置为NULL
}
void InitList(linkNode *&L)
{
	L=(linkNode *)malloc(sizeof(linkNode));  	//创建头结点
	L->next=NULL;
}
void DestroyList(linkNode *&L)
{
	linkNode *pre=L,*p=pre->next;
	while (p!=NULL)
	{	free(pre);
		pre=p;
		p=pre->next;
	}
	free(pre);	//此时p为NULL,pre指向尾结点,释放它
}
bool ListEmpty(linkNode *L)
{
	return(L->next==NULL);
}
int ListLength(linkNode *L)
{
	linkNode *p=L;int i=0;
	while (p->next!=NULL)
	{	i++;
		p=p->next;
	}
	return(i);
}
void DispList(linkNode *L)
{
	linkNode *p=L->next;
	while (p!=NULL)
	{	printf("%d ",p->data);
		p=p->next;
	}
	printf("n");
}
bool GetElem(linkNode *L,int i,ElemType &e)
{
	int j=0;
	linkNode *p=L;
	if (i<=0) return false;		//i错误返回假
	while (jnext;
	}
	if (p==NULL)				//不存在第i个数据结点
		return false;
	else						//存在第i个数据结点
	{	e=p->data;
		return true;
	}
}
int LocateElem(linkNode *L,ElemType e)
{
	linkNode *p=L->next;
	int n=1;
	while (p!=NULL && p->data!=e)
	{	p=p->next;
		n++;
	}
	if (p==NULL)
		return(0);
	else
		return(n);
}
bool ListInsert(linkNode *&L,int i,ElemType e)
{
	int j=0;
	linkNode *p=L,*s;
	if (i<=0) return false;			//i错误返回假
	while (jnext;
	}
	if (p==NULL)					//未找到位序为i-1的结点
		return false;
	else							//找到位序为i-1的结点*p
	{	s=(linkNode *)malloc(sizeof(linkNode));//创建新结点*s
		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;
	if (i<=0) return false;		//i错误返回假
	while (jnext;
	}
	if (p==NULL)				//未找到位序为i-1的结点
		return false;
	else						//找到位序为i-1的结点p
	{	q=p->next;				//q指向要删除的结点
		if (q==NULL) 
			return false;		//若不存在第i个结点,返回false
		e=q->data;
		p->next=q->next;		//从单链表中删除q结点
		free(q);				//释放q结点
		return true;
	}
}

3.双链表 3.1双链表的定义
typedef int ElemType;
typedef struct DNode		//定义双链表结点类型
{
	ElemType data;
	struct DNode *prior;	//指向前驱结点
	struct DNode *next;		//指向后继结点
} DlinkNode;

基于双链表的定义,双链表具有以下特性:
从任意节点出发可以快速找到其前驱节点和后继节点。从任意节点出发可以访问其它节点。
(我认为比单链表方便)

3.2双链表的基本使用
void CreateListF(DlinkNode *&L,ElemType a[],int n)
//头插法建双链表
{
	DlinkNode *s;
	L=(DlinkNode *)malloc(sizeof(DlinkNode));  	//创建头结点
	L->prior=L->next=NULL;
	for (int i=0;idata=a[i];
		s->next=L->next;			//将结点s插在原开始结点之前,头结点之后
		if (L->next!=NULL) L->next->prior=s;
		L->next=s;s->prior=L;
	}
}
void CreateListR(DlinkNode *&L,ElemType a[],int n)
//尾插法建双链表
{
	DlinkNode *s,*r;
	L=(DlinkNode *)malloc(sizeof(DlinkNode));  	//创建头结点
	L->prior=L->next=NULL;
	r=L;					//r始终指向终端结点,开始时指向头结点
	for (int i=0;idata=a[i];
		r->next=s;s->prior=r;	//将结点s插入结点r之后
		r=s;
	}
	r->next=NULL;				//尾结点next域置为NULL
}
void InitList(DlinkNode *&L)
{
	L=(DlinkNode *)malloc(sizeof(DlinkNode));  	//创建头结点
	L->prior=L->next=NULL;
}
void DestroyList(DlinkNode *&L)
{
	DlinkNode *pre=L,*p=pre->next;
	while (p!=NULL)
	{
		free(pre);
		pre=p;
		p=pre->next;
	}
	free(pre);
}
bool ListEmpty(DlinkNode *L)
{
	return(L->next==NULL);
}
int ListLength(DlinkNode *L)
{
	DlinkNode *p=L;
	int i=0;
	while (p->next!=NULL)
	{
		i++;
		p=p->next;
	}
	return(i);
}
void DispList(DlinkNode *L)
{
	DlinkNode *p=L->next;
	while (p!=NULL)
	{
		printf("%d ",p->data);
		p=p->next;
	}
	printf("n");
}
bool GetElem(DlinkNode *L,int i,ElemType &e)
{
	int j=0;
	DlinkNode *p=L;
	if (i<=0) return false;		//i错误返回假
	while (jnext;
	}
	if (p==NULL)
		return false;
	else
	{
		e=p->data;
		return true;
	}
}
int LocateElem(DlinkNode *L,ElemType e)
{
	int n=1;
	DlinkNode *p=L->next;
	while (p!=NULL && p->data!=e)
	{
		n++;
		p=p->next;
	}
	if (p==NULL)
		return(0);
	else
		return(n);
}
bool ListInsert(DlinkNode *&L,int i,ElemType e)
{
	int j=0;
	DlinkNode *p=L,*s;
	if (i<=0) return false;		//i错误返回假
	while (jnext;
	}
	if (p==NULL)				//未找到第i-1个结点
		return false;
	else						//找到第i-1个结点p
	{
		s=(DlinkNode *)malloc(sizeof(DlinkNode));	//创建新结点s
		s->data=e;	
		s->next=p->next;		//将结点s插入到结点p之后
		if (p->next!=NULL) 
			p->next->prior=s;
		s->prior=p;
		p->next=s;
		return true;
	}
}
bool ListDelete(DlinkNode *&L,int i,ElemType &e)
{
	int j=0;
	DlinkNode *p=L,*q;
	if (i<=0) return false;		//i错误返回假
	while (jnext;
	}
	if (p==NULL)				//未找到第i-1个结点
		return false;
	else						//找到第i-1个结点p
	{
		q=p->next;				//q指向要删除的结点
		if (q==NULL) 
			return false;		//不存在第i个结点
		e=q->data;
		p->next=q->next;		//从单链表中删除*q结点
		if (p->next!=NULL) p->next->prior=p;
		free(q);				//释放q结点
		return true;
	}
}

4.循环表 4.1循环表的简介

因为循环表是基于单链表和双链表来建立的,所以循环链表有循环单链表和循环双链表两种。


循环单链表示意图;

循环双链表示意图:

4.2循环单链表的基本使用
void CreateListF(linkNode *&L,ElemType a[],int n)
//头插法建立循环单链表
{
	linkNode *s;int i;
	L=(linkNode *)malloc(sizeof(linkNode));  	//创建头结点
	L->next=NULL;
	for (i=0;idata=a[i];
		s->next=L->next;			//将结点s插在原开始结点之前,头结点之后
		L->next=s;
	}
	s=L->next;	
	while (s->next!=NULL)			//查找尾结点,由s指向它
		s=s->next;
	s->next=L;						//尾结点next域指向头结点

}
void CreateListR(linkNode *&L,ElemType a[],int n)
//尾插法建立循环单链表
{
	linkNode *s,*r;int i;
	L=(linkNode *)malloc(sizeof(linkNode));  	//创建头结点
	L->next=NULL;
	r=L;					//r始终指向终端结点,开始时指向头结点
	for (i=0;idata=a[i];
		r->next=s;			//将结点s插入结点r之后
		r=s;
	}
	r->next=L;				//尾结点next域指向头结点
}
void InitList(linkNode *&L)
{
	L=(linkNode *)malloc(sizeof(linkNode));	//创建头结点
	L->next=L;
}
void DestroyList(linkNode *&L)
{
	linkNode *p=L,*q=p->next;
	while (q!=L)
	{
		free(p);
		p=q;
		q=p->next;
	}
	free(p);
}
bool ListEmpty(linkNode *L)
{
	return(L->next==L);
}
int ListLength(linkNode *L)
{
	linkNode *p=L;int i=0;
	while (p->next!=L)
	{
		i++;
		p=p->next;
	}
	return(i);
}
void DispList(linkNode *L)
{
	linkNode *p=L->next;
	while (p!=L)
	{
		printf("%d ",p->data);
		p=p->next;
	}
	printf("n");
}
bool GetElem(linkNode *L,int i,ElemType &e)
{
	int j=0;
	linkNode *p;
	if (L->next!=L)		//单链表不为空表时
	{
		if (i==1)
		{
			e=L->next->data;
			return true;
		}
		else			//i不为1时
		{
			p=L->next;
			while (jnext;
			}
			if (p==L)
				return false;
			else
			{
				e=p->data;
				return true;
			}
		}
	}
	else				//单链表为空表时
		return false;
}
int LocateElem(linkNode *L,ElemType e)
{
	linkNode *p=L->next;
	int n=1;
	while (p!=L && p->data!=e)
	{
		p=p->next;
		n++;
	}
	if (p==L)
		return(0);
	else
		return(n);
}
bool ListInsert(linkNode *&L,int i,ElemType e)
{
	int j=0;
	linkNode *p=L,*s;
	if (p->next==L || i==1)		//原单链表为空表或i==1时
	{
		s=(linkNode *)malloc(sizeof(linkNode));	//创建新结点s
		s->data=e;								
		s->next=p->next;		//将结点s插入到结点p之后
		p->next=s;
		return true;
	}
	else
	{
		p=L->next;
		while (jnext;
		}
		if (p==L)				//未找到第i-1个结点
			return false;
		else					//找到第i-1个结点p
		{
			s=(linkNode *)malloc(sizeof(linkNode));	//创建新结点s
			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;
	if (p->next!=L)					//原单链表不为空表时
	{
		if (i==1)					//i==1时
		{
			q=L->next;				//删除第1个结点
			e=q->data;
			L->next=q->next;
			free(q);
			return true;
		}
		else						//i不为1时
		{
			p=L->next;
			while (jnext;
			}
			if (p==L)				//未找到第i-1个结点
				return false;
			else					//找到第i-1个结点p
			{
				q=p->next;			//q指向要删除的结点
				e=q->data;
				p->next=q->next;	//从单链表中删除q结点
				free(q);			//释放q结点
				return true;
			}
		}
	}
	else return false;
}
4.3 循环双链表的基本使用
void CreateListF(DlinkNode *&L,ElemType a[],int n)
//头插法建立循环双链表
{
	DlinkNode *s;int i;
	L=(DlinkNode *)malloc(sizeof(DlinkNode));  	//创建头结点
	L->next=NULL;
	for (i=0;idata=a[i];
		s->next=L->next;			//将结点s插在原开始结点之前,头结点之后
		if (L->next!=NULL) L->next->prior=s;
		L->next=s;s->prior=L;
	}
	s=L->next;	
	while (s->next!=NULL)			//查找尾结点,由s指向它
		s=s->next;
	s->next=L;						//尾结点next域指向头结点
	L->prior=s;						//头结点的prior域指向尾结点

}
void CreateListR(DlinkNode *&L,ElemType a[],int n)
//尾插法建立循环双链表
{
	DlinkNode *s,*r;int i;
	L=(DlinkNode *)malloc(sizeof(DlinkNode));  //创建头结点
	L->next=NULL;
	r=L;					//r始终指向尾结点,开始时指向头结点
	for (i=0;idata=a[i];
		r->next=s;s->prior=r;	//将结点s插入结点r之后
		r=s;
	}
	r->next=L;				//尾结点next域指向头结点
	L->prior=r;				//头结点的prior域指向尾结点
}
void InitList(DlinkNode *&L)
{
	L=(DlinkNode *)malloc(sizeof(DlinkNode));  	//创建头结点
	L->prior=L->next=L;
}
void DestroyList(DlinkNode *&L)
{
	DlinkNode *p=L,*q=p->next;
	while (q!=L)
	{
		free(p);
		p=q;
		q=p->next;
	}
	free(p);
}
bool ListEmpty(DlinkNode *L)
{
	return(L->next==L);
}
int ListLength(DlinkNode *L)
{
	DlinkNode *p=L;
	int i=0;
	while (p->next!=L)
	{
		i++;
		p=p->next;
	}
	return(i);
}
void DispList(DlinkNode *L)
{
	DlinkNode *p=L->next;
	while (p!=L)
	{
		printf("%d ",p->data);
		p=p->next;
	}
	printf("n");
}
bool GetElem(DlinkNode *L,int i,ElemType &e)
{
	int j=0;
	DlinkNode *p;
	if (L->next!=L)		//双链表不为空表时
	{
		if (i==1)
		{
			e=L->next->data;
			return true;
		}
		else			//i不为1时
		{
			p=L->next;
			while (jnext;
			}
			if (p==L)
				return false;
			else
			{
				e=p->data;
				return true;
			}
		}
	}
	else				//双链表为空表时
		return 0;
}
int LocateElem(DlinkNode *L,ElemType e)
{
	int n=1;
	DlinkNode *p=L->next;
	while (p!=NULL && p->data!=e)
	{
		n++;
		p=p->next;
	}
	if (p==NULL)
		return(0);
	else
		return(n);
}
bool ListInsert(DlinkNode *&L,int i,ElemType e)
{
	int j=0;
	DlinkNode *p=L,*s;
	if (p->next==L)					//原双链表为空表时
	{	
		s=(DlinkNode *)malloc(sizeof(DlinkNode));	//创建新结点s
		s->data=e;
		p->next=s;s->next=p;
		p->prior=s;s->prior=p;
		return true;
	}
	else if (i==1)					//原双链表不为空表但i=1时
	{
		s=(DlinkNode *)malloc(sizeof(DlinkNode));	//创建新结点s
		s->data=e;
		s->next=p->next;p->next=s;	//将结点s插入到结点p之后
		s->next->prior=s;s->prior=p;
		return true;
	}
	else
	{	
		p=L->next;
		while (jnext;
		}
		if (p==L)				//未找到第i-1个结点
			return false;
		else					//找到第i-1个结点*p
		{
			s=(DlinkNode *)malloc(sizeof(DlinkNode));	//创建新结点s
			s->data=e;	
			s->next=p->next;	//将结点s插入到结点p之后
			if (p->next!=NULL) p->next->prior=s;
			s->prior=p;
			p->next=s;
			return true;
		}
	}
}
bool ListDelete(DlinkNode *&L,int i,ElemType &e)
{
	int j=0;
	DlinkNode *p=L,*q;
	if (p->next!=L)					//原双链表不为空表时
	{	
		if (i==1)					//i==1时
		{	
			q=L->next;				//删除第1个结点
			e=q->data;
			L->next=q->next;
			q->next->prior=L;
			free(q);
			return true;
		}
		else						//i不为1时
		{	
			p=L->next;
			while (jnext;
			}
			if (p==NULL)				//未找到第i-1个结点
				return false;
			else						//找到第i-1个结点p
			{
				q=p->next;				//q指向要删除的结点
				if (q==NULL) return 0;	//不存在第i个结点
				e=q->data;
				p->next=q->next;		//从单链表中删除q结点
				if (p->next!=NULL) p->next->prior=p;
				free(q);				//释放q结点
				return true;
			}
		}
	}
	else return false;					//原双链表为空表时
}

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号