数据结构之链表

数据结构之链表

2.1 单链表的定义与表示

线性表链式存储结构的特点是:用一组任意的存储单元存储线性表的数据元素(可以是连续或者不连续)。所以除了存储本身信息(数据域)之外还需存储一个与后继数据元素之间关系的信息(指针域)。

这两部分组成的数据元素的存储映像,称为结点。n个结点链结成一个链表即为线性表的链式存储结构。由于只有一个指针域,又称为线性链表或单链表。

2.2 指针的常用操作

1.类型定义

typedef struct LNode{
	Elemtype date;
	struct Lnode *next;
}LNode,*LinkList;

2.变量定义

    LinkList l;
    LNode* p,* s;

3.重要操作

	p = L;//p指向头结点
	s = L->next;//s指向首元结点
	p = p->next;//p指向下一结点

4.单链表的初始化

/*【算法步骤】
	① 生成新节点作为头结点,用头指针L指向头结点
	② 头结点的指针域置空
*///【算法描述】
	Status intlist(ListList &L){
		L = new Lnode;//L = (LinkList)mallo(sizeof(LNode));//生成新结点作为头结点,给指针;
		L->next = NULL;//指针域置空
		return 1;
	} 	

5.补充基本算法

//补充 1:判断链表是否为空
//判断头结点的指针域是否为空。就是头结点指没指向别的结点?
int ListEmpty(LinkList L){
	if(l->next) return 0;
	else return 1;
}

请添加图片描述

//补充 2:单链表的销毁(啥都没了,头指针也没了)
/*从头指针开始依次释放所有结点。
我们的思路就是
循环条件:如果这个指针不空就执行下去	L!=NULL;或者L
① 先让P指针指向首节点		p = L;
② 让头指针指向第二个结点	L = L->next;
③ 删除这个结点			delete p;
结束条件:指针空了就停	L == NULL;或者P == NULL;
*/
Status DestroyList(LinkList &L){
	LinkList p;
	while(L){
		p = L;
		L = L->next;
		delete p;
	}
	return 1;
}

请添加图片描述

//补充 3:清空链表(最终结果只剩下头指针)
/*从头指针开始,依次释放所有结点
我们的思路是
循环条件:只要还有链表就一直清空!p!= NULL;
① 因为要留头指针嘛所以我们从首元结点开始 p = L->next;
② 我们需要另外一个指针q帮我们存下一个结点,原因是如果先删除当前结点,那么下一个结点的地址去哪里找呢?我们找不到了,所以需要另外一个结点q存下一个结点的地址.
q = p->next; delete p; 
③ 然后第二个结点是不是就变成“首元结点了呢”,所以再让p从“新的首元结点开始”,q指向下一个结点。 p = q; q = q->next;
结束条件:全删完就完事了嘛,所以当p的结点是空的时候就结束。p == NULL;或者p;
④ 让头指针的指针域指向空就完事了。L->next = NULL;
*/
Status ClearList(LinkList &L){
	LinkList p,q;//LNode* p,* q;
	p = L->next;
	while(p){
		q = p->next;
		delete p;
		p = q;
	}
	L->next = NULL;
	return 1;
}

请添加图片描述

//补充 4:求单链表的表长
/*从首元结点开始,依次计数所有结点
我们的思路是
循环条件:既然要遍历那就是标志为空喽	p == NULL;或者p
① 从首元结点开始	p = L->next;
② 因为要计数所以需要一个计数器 int cut = 0;
③ 让p后移 p = p->next;
结束条件:p指向空代表链表没了所以 p == NULL;
*/
int ListLength_L(LinkList L){
	LinkList p;
	p = L->next;
	int i = 0;
	while(p){
		i++;
		p = p->next;
	}
	return i;
}

请添加图片描述

2.3 单链表基本操作的实现

1.单链表的取值(取单链表中第i个元素的内容)

/*因为链表事顺序存储不能像随机存取结构顺序表一样随便拿,所以需要遍历,然后又要取第i个元素的内容,所以需要计数器。
注意:如果正常的话他让你取的应该是在链表长度内的,如果一个链表长六个,他要是一个的话拿p到第六个往第七个走的时候就指向了空,我们就结束,如果要是小于链表长度比如0,-1,我们直接就结束。
① 从第一个结点开始顺序扫描,让p指向首元结点 p = L->next;
② 定义一个计数器,初值为1 int cut = 1;
③ 当p指向下一结点时,cut++;
结束条件:当计数器与i相等时结束 j == i;
*/
Status GetElme_L(LickListL,int i,ElemType &e){
	p = L->next;
	int j = 1;
	while(p&&j<i){		//计数器
		p = p->next;
		j++;
	}
	if(!p || j>i) return 0;	//异常事件
	e = p->data;		//取元素
	return 1;
}

2.单链表的查找(找有没有元素与被找的相等)
按值查找-根据指定数据获得该数据所在位置(地址)

/*顺序查找 对比数据域和要求的值,返回p指针的值
我们的思路
循环条件:找到了或者没有结束
① 从第一个结点起,依次跟e比较; p = L->next;
② 找到了就返回链表中的地址如果是要位置的话,需要加上计数器;
③ 如果遍历一遍以后都没有找到与其相等的元素,就返回0或者NULL;其实就是p的值;
*/

//返回地址
LNode* LocateElem_L(LinkList L,Elemtype e){
	p = L->next;
	while(p && p->next!=e)
		p = p->next;
	return p;
}
//返回位置
int LocateElme_L(LinkList L;Elemtype e){
	p = L->next; int cut = 0;
	while(p && p->date!=e){
		p = p->next;
		cut++;
	}
	if(p) return cut;
	else return 0;
}

3.单链表的插入(在第i个结点钱插入新结点)

/*在第i个地方插入新元素,就是让a(i-1)的指针域指新元素的数据域,让新元素的指针域指ai的数据域
我们的思路
① 找到i-1的结点  	  	遍历嘛
② 生成数据域为e的新节点s 	创建结点嘛
③ 插入新结点:
			1.让新结点指向结点ai 原先ai的指针域存在ai-1的指针域里了; 所以 s->next = p->next;
			2.结点ai-1的指针域指向新结点; p->next = s;
*/

Stauts Lisinsert_L(LinkList&L,int i;ElemTYpe e){
	p = L;int j = 0;
	while(p && j<i-1){		//寻找i-1个结点,p指向i-1结点
	 	p = p->next;
		j++;
	}
	
	if(!p || j>i-1)return 0;//非法插入
	
	s = new LNode; s->date = e;//生成新节点s
	
	s->next = p->next;	//核心算法
	p->next = s;
	return 1;
}

请添加图片描述

4.单链表的删除(删除第i个结点)

/*找到第i个元素,让ai-1指向ai+1
我们的思路
① 首先找到ai-1存储位置p,如果有需要的话保存ai的值
② 让p的指针域指向ai+1,ai+1的地址在ai中; p = p->next->next;
③ 释放ai 需要事先再用一个存一下 因为删完就没了 q = p->nest; delete q;
*/
Status ListDalete_L(LinkList &L,int i,ElmeType &e){
	p = L;j = 0;q;i;
	while(p->next && j<i-1){p = p->next;j++;}//遍历找到i-1
		
	if(!(p->next) || j>i-1) return 0;//异常删除
	
	q = p->next;//临时存储要删的地址,防止被释放
	p->next = q->next;//核心算法 因为提前存好了就不用p->next->next了
	e = q->next;//保存删除结点的数据域,看需求的
	delete q;
	return 1;
} 

请添加图片描述

时间效率分析
1.查找:我们需要顺着链一直找(顺序存取),最好是1,最坏是n,所以O(n);
2.插入与删除
因为线性链表不需要移动元素,只要改指针,易班是O(1);
但是如果不知道具体位置,需要查找的话,又需要从头来,所以是O(n);

5.单链表的建立—头插法(元素插入在链表头部,也叫前插法)

我们的思路
① 从一个空表开始,重复读入数据;
② 生成新结点,将读入数据存放到新结点的数据域中
③ 从最后一个结点开始,依次将各结点插入到链表的前端

在这里插入图片描述

尾插法

在这里插入图片描述

循环链表

在这里插入图片描述

双向链表在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值