链表学习总结

王道视频笔记

链表

一、单链表

1.1 单链表定义及初始化

/1.单链表定义
typedef struct LNode{            //LNode:结点 
	ElemType data;       //数据域
	struct LNode*next;   //指针域,指向下个结点
}LNode,*LinkList;//LNode强调指结点,LinkList强调指单链表。
//不带头结点的单链表初始化
LinkList L ;
//初始化一个不带头结点的单链表
/*
  &L直接引用实参,不会生成形参,因此省略了赋值操作这一步。
  函数会直接对实参进行操作,因此会改变实参的值
*/
bool InitList(Linklist &L){
	L = NULL;            //空表,暂时无结点
	return ture;
}
//带头结点的单链表声明
LinkList L ;//建立一个带头结点的空链表。
//初始化一个带头结点的单链表:不存储数据
bool InitList(Linklist &L){
	L = (LNode*)malloc(sizeof(LNode));//分配一个头结点
	if(L==NULL)//空间分配失败会返回空指针
		return false;
	L->next = NULL:
	return ture;
}

1.2单链表插入

以下皆是带头结点单链表操作。

1.2.1按位序插入
bool ListInsert(Linklist &L,int i ,ElemType e){
	if(i<1)//结点从1开始
		return false;
	LNode *p;//指针p指向当前扫描的结点
    int j=0; //当前p指向第几个结点
	p = L;   //L 指向头结点不含数据,含有第一个结点的首地址,可以看做Node0
	while(p!=NULL&&j<i-1){//找到i-1个结点
		p = p->next;
		j++;
	}
	if(p==NULL)
		return false;
	LNode *s = (LNode*)malloc(sizeof(LNode));//为新结点分配空间
	s->data = e;
	s->next = p->next;//s结点 --> i结点 
	p->next = s;      //i-1结点-->s结点
	return true;
}
1.2.2指定结点后插入元素e
//在p结点后插入元素e
bool InsertNextNode(ElemType *p,ElemType e){
	if(p==NULL)//该结点不存在
		return false;
	LNode *s = (LNode*)malloc(sizeof(LNode));
	if(s==NULL)
		return false;
	s->data = e;
	s->next = p->next;
	p->next = s;
	return true;
}

1.2.3指定结点前插入元素e

//在p结点前插入元素e
//当前p结点的数据后移到新结点 , 再将新结点的数据赋予p结点
bool InsertPreNode(ElemType *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;
}

1.3删除

1.3.1按位序删除
bool ListDelete(Linklist &L,int i,ElemType &e){
	if(i<1)
		return false;
	LNode*p;//指向当前扫描的结点
	int j = 0;//扫描第几个结点
	p = L;  //结点0
	while(p->next!=NULL&& j<i-1){//循环扫描到i-1结点
		p = p->next;
		j++;
	}
	if(p->next==NULL)//不存在i结点
		return false;
	
	LNode*temp = p->next;
	e = temp->data;//保存数据
	p->next = temp->next;
	free(temp);
	return false;
}
1.3.2指定结点删除
//如果p不是最后一个结点
bool ListDeleteNode (LNode *p){
	if(p==NULL)
		return false;
	LNode *temp = p->next;//记录p后一结点,数据转移到p结点,删除后一个结点
	p->data = p->next->data;
	p->next = p->next->next;
	free(temp);
	return true;
}
//删除最后一个结点p
bool ListDeleteFinNode (Linklist &L,LNode *p){
	if(p==NULL)
		return false;
	LNode *q =L;//由于是p是最后一个结点,只能从头查找。
	while(q->next!=p){//找到前一个结点
		q = q->next;
	}
	q->next = p->next;
	free(p);
	return true;
}

1.4、查找

1.4.1按位序查找
LNode * GetElem(LinkList L,int i){
	if(i<0)
		return NULL;//若i小于1,返回NULL,
	LNode *p=L;
	int j =0;
	while(p!=NULL&&j<i){//若i大于实际节点数,返回NULL,若为0,返回LL
		p = p->next;
		j++;
	}
	return p;
}
1.4.2插入与删除用查找函数封装
//插入
bool ListInsert(Linklist &L,int i ,ElemType e){
	if(i<1)//结点从1开始
		return false;
	//通过查找函数
	LNode *p = GetElem(L,i-1);//找到i-1个结点
	return InsertNextNode(p,e);
}
//删除
bool ListDelete(Linklist &L,int i,ElemType &e){
	if(i<1)
		return false;
	//查找函数找到i结点
	LNode*p = GetElem(L,i-1);
	//删除指点结点函数
	if(p==NULL&&p->next==NULL)//不存在i结点
		return false;
	LNode*temp = p->next;
	e = temp->data;//保存数据
	p->next = temp->next;
	free(temp);
	return false;
}
1.4.3按值查找
//按值查找 
LNode * LocatElem(LinkList L,Elemtype e){
	LNode *p = L->next;
	//从第一个结点找起
	while(p!=NULL&&p->data!=e)
		p = p->next;
	return p;//返回该结点,否则返回NULL
}

1.5 计算链表长度

int ListLength(LinkList L){
	int len = 0;
	LNode *p = L;
	while(p->next!=NULL){
		p = p->next;
		len++;
	}
	return len;
}

1.5 判断链表是否为空

bool Empty(LinkList L){
	if(L->next == NULL)
		return true;
	else
		return false;
}

1.6 销毁链表

void DestoryList(LinkList &L){
	LNode*temp;
	while(L->next!=NULL){//删除头结点直至剩头结点
		temp = L->next;
		L-next = L->next->next;
		free(temp);
	}
	free(L);	//释放头结点
	L =NULL;	//指向NULL
}

二、链表建立

2.1尾插法建立单链表

LinkList list_TailInsert(LinkList &L){
	int x;			//ElemType:int
	L = (LinkList)malloc(sizeof(LNode));
	LNode*s,*r=L;
	scnaf("%d",&x);   //输入结点的值
	while(x!9999){		//链表结束条件
		s = (LNode*)malloc(LNode);
		s->data = x;
		r->next = s;
		r =s;				//r指向新的表尾结点,
		scnaf("%d",&x);
	}
	r->next = NULL;           //尾结点指向NULL;
	return L;
}

2.2头插法建立单链表

//逆向插入
 LinkList list_headInsert(LinkList &L){
	int x;			//ElemType:int
	L = (LinkList)malloc(sizeof(LNode));
	L->next = NULL;
	scnaf("%d",&x);   //输入结点的值
	while(x!9999){		//链表结束条件
		s = (LNode*)malloc(LNode);
		s->data = x;
		s->next = L->next;
		L->next = s;
		scnaf("%d",&x);
	}
	return L;
}

三、双链表

3.1双链表结点类型定义

//***********************双链表结点类型********************
typedef struct DNode{
	ElemType data;			  //数据域
	struct DNode *prior,*next;//前驱指针和后继指针
}DNode,*DLinklist;

3.2 双链表初始化(带头结点)

//**********************初始化********************
bool InitDLinkList(DLinklist &L){
	L = (DLinklist)malloc(sizeof(DNode));分配头结点
	if(L==NULL)
		return false;//内存分配失败
	L->prior = NULL;
	L->next = NULL;
	return true;
}

3.3 双链表指定节点插入(带头结点)

//********************指定节点p后插入********************
//DNode  p->s 
bool InsertNextDNode(DNode*p,DNode*s){
	if(p==NULL||s==NULL)
		return false;
	//后插:后-> 中s-> 前p
	if(p->next != NULL)//后:p下个结点
		p->next->prior = s;
	s-next = p->next;//中:s
	s->prior = p;
	p->next = s;//前:p
}
//DNode s->p结点前插入
bool InsertNextDNode(DNode*p,DNode*s){
	if(p==NULL||s==NULL)
		return false;
	//前插:前-> 中-> 后
	p->prior->next = s;//前:s前一个结点
	s->prior = p->prior;//中:s
	s->next = p;
	p->prior = s;//后:p
}

双链表按位序操作与单链表一样,如上注意前驱与后驱的赋值。

3.4 双链表是否为空(带头结点)

bool Empty(DLinklist L){
	if(L->next == NULL)
		return true;
	else
		return false;
}

3.5删除结点与销毁链表与单链表一样,就不写了。

四、循坏链表

最后一个节点指向第一个节点。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言中的环形双向链表是通过`container/ring`包来实现的。在这个包中,首先我们定义了一个`Ring`结构体,它包含了指向前一个和后一个元素的指针,以及一个值字段用于存储链表的值。这个结构体通过方法来实现链表的各种操作。 要生成一个链表,我们可以使用`New`函数来创建一个空的环形链表,然后使用`Link`方法将不同的元素连接起来。对于每个元素,我们可以使用`Value`字段来存储相应的值。 在环形链表中,我们可以通过`Move`方法来移动当前指针到下一个或上一个元素,并可以使用`Prev`和`Next`方法来获取前一个和后一个元素。 要删除链表中的元素,我们可以使用`Unlink`方法将指定的元素从链表中移除。要插入一个新元素,我们可以使用`Link`方法将新元素插入到指定元素之前。 对于环形双向链表的查询操作,我们可以使用`Do`方法来遍历整个链表并对每个元素执行指定的函数。另外,我们还可以使用`Len`方法来获取链表的长度。 总结起来,Go语言的环形双向链表通过`container/ring`包提供了一种简单而灵活的数据结构,可以方便地进行链表的增删改查操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Go语言标准库学习之container——Go语言如何实现单链表、循环链表、双向链表、堆](https://blog.csdn.net/random_w/article/details/108096981)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值