线性表的链式存储结构

单链表

通过一组任意的存储单元来存储线性表中的数据元素。

常用操作

Empty();判断单链表是否为空

InitLinkList();单链表的初始化 带头结点

LinkInsert();给定位序后插入结点

InsertNextNode();在指定结点(p)后插入新的节点s,其值为e

InsertPrior();给定节点前插入新节点

ListDelete();按位序删除结点(带头结点)

DeleteNode();删除指定的结点 

GetElem(L);给定需要查找的位置,在单链表里进行查找

结构体定义的两种方式在代码里面
class Linklist
{
	//定义一个ElemType类型的数据类型
	typedef int ElemType;

	//1.定义一个单链表节点类型
	typedef struct LNode { //Typedef关键字--<数据类型><别名>   
		ElemType data; //定义单链表节点的数据域
		struct LNode *next; //定义单链表的指针域
	}LNode, *LinkList; //用Linklist指向struct LNode的指针     L表示这是一个指向第一个单链表的指针
	

	/*//2.第二种定义结构体的方式
	typedef struct LNode { //Typedef关键字--<数据类型><别名>   
		ElemType data; //定义单链表节点的数据域
		struct LNode *next; //定义单链表的指针域
	}LNode;

	typedef struct LNode Lnode;
	typedef struct LNode *Linklist;
	*/


	//判断单链表是否为空
	bool Empty(LinkList L) {
		if (NULL)
		{
			return false;
		}
		else
		{
			return true;
		}
	}

	/*//单链表的初始化 不带头结点
	LinkList InitLinkList(LinkList &L) {
		struct LNode *L = NULL;   //空表暂时还没有数据,防止脏数据 不可以给L赋int类型的值
		return L;
	}*/

	//单链表的初始化 带头结点
	bool InitLinkList(LinkList &L) {
		LNode * L;
		LinkList L;
		LNode *L = ( LNode *)malloc(sizeof( LNode));
		Empty(L);
		L->next = NULL;
		return true;
	}

	bool LinkInsert(LinkList &L, int i, ElemType e) {
		if (i < 1)
			return false;
		LNode *p; //指针p指向当前扫描到的结点
		int j = 0; //当前p指向的结点的位序
		p = L;  //将L的节点位置给P的结点位置,头结点是第0个结点
		
		while (p != NULL && j < i - 1) {  //循环找到第i-1个结点  找到插入的节点的位置
			p = p->next;
			j++;
		}
		if (p==NULL)  //判断结点是否为空如果为空则返回空值
		{
			return false;
		}
		return InsertNextNode(p,e);  //下方写的在指定结点的后插操作
	}

	bool InsertNextNode(LNode *p,ElemType e) { //在指定结点(p)后插入新的节点s,其值为e
		if (p == NULL) {
			return false;
		}
		LNode *s = (LNode *)malloc(sizeof(LNode));
		if (s==NULL) //内存分配失败
		{
			return false;
		}
		s = p;
		s->data = e;
		s->next = p->next;
		p->next = s;
		return true;
	}

	/*1.第一种实现方式 将头指针也传入进去通过循环找到 要插入的p结点的前驱结点的i位置,再用按位插入的方式
	bool InsertPrior(LinkList L, LNode *p, ElemType e) {

	}
	*/

	//2. 第二种实现方式 在指定结点中插入一个新结点 然后将前后两个结点的值互换位置
	bool InsertPrior(LNode *p, ElemType e) {
		if (p == NULL) {
			return false;
		}

		LNode *s = (LNode *)malloc(sizeof(LNode));
		if (s == NULL) //内存分配失败
		{
			return false;
		}
		s->data = p->data;
		p->data = e;
		s->next = p->next;
		p->next = s;
		return true;
	}
	
	//按位序删除结点(带头结点)
	bool ListDelete(LinkList L,int i,ElemType &e) {
		if (i<1)
		{
			return false;
		}
		LNode *p;
		int j = 0;
		p = L;

		while (p!= NULL&&j<i-1)
		{
			p = p->next;
			j++;
		}
		if (p->next==NULL||p==NULL)
		{
			return false;
		}
		LNode *q = p->next;
		e = q->data;
		p->next = q->next;
		free(q);  //如果q指针不释放 那么则会造成内存泄漏 成为野指针 且值会存在
		return true;
	}
	bool DeleteNode(LNode *p) { //删除指定的结点 令删除结点后面结点的值直接给目标结点,再去删除后面结点,则可完成要求
			//如指定删除后面的结点为NULL,则无法实现操作。
		LNode *q = p->next;   //此实现方式时间复杂度为O(1)
		p->data = p->next->data;
		p->next = q->next;
		free(q);
		return true;
	}
	bool GetElem(LinkList L ,int i) { //给定需要查找的位置,在单链表里进行查找 返回0或1;
		int j=0;
		if (i<1 )  //判断输入的位序是否合法
		{
			return NULL;
		}
		LNode *p;
		p = L;
		while (p!=NULL&&j<i)   //循环查找所给位点;
		{
				p = p->next;
				j++;
				return true;			
		}
		return p;

	}

	LNode* LocateElem(LinkList L,ElemType e){ //按值查找
		LNode *p = L->next;
		while (p!=NULL&&p->data!=e)
		{
			p = p->next;
		}
		return p;
	}
	int Length(LinkList L) { //统计表长
		int len = 0;
		LNode *p = L->next;
		while (p ->next= NULL)
		{
			p = p->next;
			len++;
		}
		return len;
	}

};

感想

1.按位查找 

注意与顺序表对比

单链表不具备随机扫描的特性,只能依次扫描

2.按值查找

3.求单链表的长度

4.key

三种基础操作的时间复杂度都是O(n)

如何循环扫描各个结点的代码逻辑

注意边界条件的处理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只求学猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值