线性表之链表

线性表之链表

本篇继上篇继续讲解链式存储的实现和操作方法

导航顺序表 链接放在此地

链表

特点:链表中相邻的的元素ai和ai+1在内存中位置LOC(ai)和LOC(ai+1)不一定是连续的,就是计算机内存内存地址是不一定连续(随机的)【具体参见下面的两种插入法】

定义补充

// filename : linklist.h
#ifndef __LINKLIST_H__
#define __LINKLIST_H__

typedef int ElemType;

typedef struct LNode{
	ElemType data;	
	struct LNode *next;
}LNode, *LinkList;

void List_HeadInsert(LinkList *L);
void List_TailInsert(LinkList *L);
void Traverse_List(LinkList L);
LNode *GetElem(LinkList L, int i);
int ListLen(LinkList L);
void List_InsertNode(LinkList *L,int i, ElemType e);
ElemType List_DeleteNode(LinkList *L, int i);

#endif

对链表进行初始化

链表初始化分为两种:头插法和尾插法

头插法

头插法:顾名思义 就是每一个新的节点就插入到头节点后面第一个数据节点的后面 此方法初始化 是逆序的

具体见下图

在这里插入图片描述

代码实现
// filename : main.c
void List_HeadInsert(LinkList *L)
{
	int x;
	LNode *s;
	*L = (LinkList)malloc(sizeof(LNode));
	if (*L == NULL){
		fprintf(stderr, "malloc() fail,line:%d\n", __LINE__);
		exit(1);
	}
	(*L)->next = NULL;
	fscanf(stdin, "%d", &x);
	while (x != 9999)
	{
		s = (LinkList)malloc(sizeof(LNode));
		if (s == NULL){
			fprintf(stderr, "malloc() fail,line:%d\n", __LINE__);
			exit(1);
		}
		s->data = x;
		s->next = (*L)->next;
		(*L)->next = s;
		fscanf(stdin, "%d", &x);
	}
}

尾插法

尾插法:顾名思义 就是每一个新节点都插入到尾节点的后面(即插入到最后) 此方法初始化 是顺序的

具体见下图

在这里插入图片描述

代码实现
// filename : main.c
void List_TailInsert(LinkList *L)
{
	int x;
	LNode *s = NULL;
	LNode *pN = NULL;
	*L = (LinkList)malloc(sizeof(LNode));
	if (*L == NULL)
	{
		fprintf(stderr, "malloc() line:%d\n", __LINE__);
		exit(1);
	}
	(*L)->next = NULL;
	pN = (*L);
	fscanf(stdin, "%d", &x);
	while(x != 9999)
	{
		s = (LinkList)malloc(sizeof(LNode));
		if (s == NULL)
		{
			fprintf(stderr,"malloc() line:%d\n", __LINE__);
			exit(1);
		}
		s->data = x;
		s->next = NULL;
		pN->next = s;
		pN = pN->next;
		fscanf(stdin, "%d", &x);
	}
}

链表的遍历

实现思路:由于每一个节点都指向下一个节点,而最后一个节点的指针域是NULL,通过while去判断当前接待你的指针域是否为NULL , 这就是我们的遍历思路

具体实现如下

代码实现
// filename : main.c
void Traverse_List(LinkList L)
{
	LNode* pN = NULL;
	pN = L->next;
	while(pN != NULL)
	{
		printf("%d->", pN->data);
		pN = pN->next;
	}
	printf("NULL\n");
}

获取链表长度

实现思路:获取长度跟链表的遍历差不离儿 在遍历的基础上增加一个计数器,每循环一次加一

具体实现如下

// filename : main.c
int ListLen(LinkList L)
{
	LNode *pN = L->next;
	int len = 0;
	while (pN != NULL)
	{
		len++;
		pN = pN->next;
	}
	return len;
}

获取指定位置的节点

实现思路:通过遍历,增加计数器,和给出i比较,如果相等退出循环 返回当前的节点,如果不相等改变指针指向下一个位置

具体实现如下

// filename : main.c
LNode *GetElem(LinkList L, int i)
{
	if (i < 1 && ListLen(L) > i)
	{
		fprintf(stderr, "GetElem parameter i error line:%d\n", __LINE__);
		exit(1);
	}
	int count = 1;
	LNode *pN = L->next;
	while (pN != NULL)
	{
		if (count++ == i)
		{
			return pN;
		}
		else
		{
			pN = pN->next;
		}
	}
}

向链表中指定位置插入一个节点

实现思路:获取要插入节点的前一个节点,创建一个新的节点, 改变前一个指针的指向,在此要改变指针的先后顺序,防止链表断开,首先令新的节点指向要插入位置的节点,然后在改变插入位置前一个位置的指针

具体实现如下

void List_InsertNode(LinkList *L,int i, ElemType e)
{
	if (i < 1 && ListLen(*L) > i)
	{
		fprintf(stderr, "List_InsertNode() parameter i error line:%d\n", __LINE__);
		exit(1);
	}
	LNode *s = (LinkList)malloc(sizeof(LNode));
	if (s == NULL)
	{
		fprintf(stderr, "malloc() error line:%d\n", __LINE__);
		exit(1);
	}
	LNode *pN = GetElem(*L, i-1);
	s->data = e;
	s->next = pN->next;
	pN->next = s;
}

删除指定位置的节点

实现思路:找到要删除节点的前一个节点,更改前一个节点的指针指向要删除位置节点的下一个节点,注意c语言要释放掉内存空间

具体实现如下

ElemType List_DeleteNode(LinkList *L, int i)
{
	if (i < 1 && ListLen(*L) > i)
	{
		fprintf(stderr, "List_DeleteNode() parameter i error line:%d\n", __LINE__);
		exit(1);
	}
	ElemType e;
	LNode *qN = NULL;
	LNode *pN = GetElem(*L, i-1);
	qN = pN->next;
	e = qN->data;
	pN->next = qN->next;
	free(qN);
	return e;
}

代码地址 阿里云盘地址:https://www.aliyundrive.com/s/kVhr2EpQ5Dg 提取码:7zr2

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值