数据结构——单链表

一、链表的定义

链表是一种物理存储单元上非连续、非顺序的存储结构数据元素的逻辑顺序是通过链表中的指针链接次序实现的。

一般来说,数组的存储方式是这样的:

而链表的存储方式是这样的:

可见链表的是通过指针next进行联系,就像火车一样头连尾的形式。

链表包含数据域指针域。

二、链表的建立

1.初始化一个单链表的结点

typedef int ElemType;
typedef struct LNode//定义单链表的节点类型
{
	ElemType  data;//每个节点存放一个数据类型
	struct LNode *next;//指针指向下一个节点
}LNode,*LinkList;//struct LNode重命名为LNode,用LinkList来表示这是一个指向struct LNode 的指针

注:可以将int改为你想用的元素类型,为了统一写法而换成ElemType。

LNode*和LinkList本质上是一样的,LNode*强调这是一个结点,LinkList强调这是一个单链表。

2.初始化一个空链表(带头结点)

为了方便写代码,一般链表都带头结点,本文写的也都是带头结点的。

//初始化一个空链表
bool InitList(LinkList &L)
{
	L = (LNode *)malloc(sizeof(LNode));//分配一个头节点
	if (L == NULL)//内存不足,分配失败
		return false;
	L->next = NULL;//头节点之后暂时没有节点
	return true;
}

3.头插法建立单链表

//头插法建立单链表
LinkList List_HeadInsert(LinkList& L)//逆向建立单链表
{
	LNode* s;
	int x;
	L = (LNode*)malloc(sizeof(LNode));//创建头结点
	L->next = NULL;//初始为空链表
	scanf("%d", &x);//输入结点的值
	while (x != 9999)
	{
		s = (LNode*)malloc(sizeof(LNode));
		s->data = x;
		s->next = L->next;
		L->next = s;//将新结点插入表中,L为头指针
		scanf("%d", &x);
	}
}

   4.尾插法建立单链表

//尾插法建立单链表
LinkList List_Taillnsert(LinkList& L)//正向建立单链表
{
	int x;//设ElemType为整形
	L = (LinkList)malloc(sizeof(LNode));//设置头结点
	LNode* s, * r = L;//r为表尾指针
	scanf("%d", &x);//输入结点的值
	while (x != 9999)
	{
		s = (LNode*)malloc(sizeof(LNode));
		s->data = x;
		r->next = s;
		r = s;//r指向新的表尾结点
		scanf("%d", &x);
	}

	r->next = NULL;//尾结点指针置空
	return L;
}

     5.按位序插入(在第i个位置插入元素e)

bool ListInsert(LinkList& L, int i, ElemType e)
{
	if (i < 1)
		return false;
    LNode*p;
	int j = 0;//当前p指向的哪个结点
	p = L;//p指向头结点,头结点是第0个结点(不存数据)
	while (p != NULL && j < i - 1)//循环找到i-1个结点
	{
		p = p->next;
		j++;
	}
	if (p == NULL)//i值不合法
		return false;
	LNode* s = (LNode*)malloc(sizeof(LNode));
	s->data = e;
	s->next = p->next;
	p->next = s;//将结点s连到p之后
	return true;//插入成功
	return InsertNextNode(p, e);
}

6.指定节点后插

bool InsertNextNode(LNode* p, ElemType e)
{
	if (p == NULL)//i值不合法
		 return false;
	 LNode* s = (LNode*)malloc(sizeof(LNode));
	 if (s == NULL)//内存分配失败
		 return false;
	 s->data = e;
	 s->next = p->next;
	 p->next = s;//将结点s连到p之后
	 return true;//插入成功
}

7.指定节点前插

//前插操作:在p结点之前插入结点s
bool InsertPriorNode(LNode *s,LNode *p)
{
	if (p==NULL||s==NULL)
		return false;
	s->next = p->next;
	p->next = s;//s连到p之后
	ElemType temp = p->data;//交换数据域部分
	p->data = s->data;
	s->data = temp;
	
}

8.删除指定节点


//删除指定结点p
bool DeleteNode(LNode* p)
{
	if (p == NULL)
		return false;
	LNode* q = p->next;//令q指向*p后续结点
	p->data = q->data;//和后续结点交换数据域
	p->next = q->next;//将*q结点从链中断开
	free(q);//释放后续结点的存储空间
	return true;
}

9.按位查找,返回第i个元素

//按位查找,返回第i个元素(带头结点)
LNode* GetElem(LinkList& L, int i)
{
	if (i < 0)
		return NULL;
	LNode* p;//指针p指向当前扫描到的结点
	int j = 0;//指针p当前指向哪个结点
	p = L;//L指向头结点,头结点是第0个结点(不存数据)
	while (p != NULL && j < i)//循环找到第i个结点
	{
		p = p->next;
		j++;
	}
	return p;
}

10.按值查找,找到数据域为e的结点

//按值查找,找到数据域==e的结点
LNode* LocateElem(LinkList& L, int e)
{
	LNode* p = L->next;//从第一个结点开始查找数据域为e的结点
	while (p != NULL && p->data != e)
	{
		p = p->next;
	}
	return p;//找到后返回该结点指针,否则返回NULL
}

暂时总结那么多,后面有时间想起来再补

  • 30
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值