【23考研】408代码题参考模板——链表

对应视频:23考研408数据结构代码题参考模板(链表)
红色的为必须掌握
有多个模板的只要掌握一种即可。

单链表

单链表结点结构体

struct node{
	int data;//数据
	node *next;//指向下一个结点的指针 
};

其中数据域data的类型可以根据需要修改成其他的。

单链表中间插入结点

模板1

以下两段代码本质是一样的,只不过一个在函数中new结点,一个结点在外面new好然后通过参数传进来

void insert(node *p,int value){
	//在p指向结点的后面插入一个值为value的结点
	
	//申请新节点的空间,上面是C写法,下面是C++写法 
	//node *q=(node*)malloc(sizeof(node));
	node *q=new node; 
	
	q->data=value; //先把数据放进去 
	
	//将q结点连进去 
	q->next=p->next;
	p->next=q;
}
void insert(node *p,node *q){
	//在p指向结点的后面插入一个结点q 
	
	q->next=p->next;
	p->next=q;
}

模板2

以下两段代码本质是一样的,只不过一个在函数中new结点,一个结点在外面new好然后通过参数传进来

void insert(node *p,int value){
	//在p指向结点的后面插入一个值为value的结点
	
	//申请新节点的空间,上面是C写法,下面是C++写法 
	//node *q=(node*)malloc(sizeof(node));
	node *q=new node;
	
	q->data=value; //先把数据放进去 
	
	//将q结点连进去 
	node *r=p->next; //r可能指向NULL,但不影响
	p->next=q;
	q->next=r;

}
void insert(node *p,int value){
	//在p指向结点的后面插入一个结点q 
	
	node *r=p->next; //r可能指向NULL,但不影响
	p->next=q;
	q->next=r;
}

单链表中删除结点

以下两段代码本质是一样的,只不过一个是将删除的结点空间free掉,一个是返回(可能有其他用途,就是将这个结点从链表中摘下来)

void del(node *p){
	//删除p的后一个结点
	//这里不考虑q为NULL的情况 
	
	node *q=p->next;//q为要删除的结点 
	p->next=p->next->next; 
	
	//释放结点空间,上面是C写法,下面是C++写法 
	//free(q); 
	delete q;
}
node* del(node *p){
	//删除p的后一个结点,并将该结点返回 
	//这里不考虑q为NULL的情况 
	
	node *q=p->next;//q为要删除的结点 
	p->next=p->next->next; 
	
	return q; //将从链表中删除的结点返回 
}

遍历链表(以求链表长度和查找元素为例)

模板1

int length(node *head){
	//返回单链表的长度
	
	int cnt=0; //计数器,初始为0 
	
	//遍历单链表中的所有结点 
	for(node *p=head->next;p!=NULL;p=p->next){
		cnt++; //计数器+1 
	} 
	
	return cnt;  
} 
node* find(node *head,int value){
	//查找单链表中是否有元素value
	//有则返回该结点,无则返回NULL
	
	for(node *p=head->next;p!=NULL;p=p->next){
		if(p->data == value){
			//找到了,返回该结点 
			return p;
		}
	} 
	
	return NULL;//没找到,返回NULL 
} 

模板2

int length(node *head){
	//返回单链表的长度
	
	int cnt=0; //计数器,初始为0 
	
	//遍历单链表中的所有结点 
	node *p=head->next; //p指向链表中第一个元素所在的结点 
	while(p!=NULL){
		cnt++; //计数器+1 
		p=p->next;//p指向下一个结点 
	} 
	
	return cnt;  
} 
node* find(node *head,int value){
	//查找单链表中是否有元素value
	//有则返回该结点,无则返回NULL
	
	node *p=head->next;//p指向链表中第一个元素所在的结点
	while(p!=NULL){
		if(p->data == value){
			//找到了,返回该结点 
			return p;
		}
		p=p->next;//p指向下一个结点
	} 
	
	return NULL;//没找到,返回NULL 
} 

头插法建立单链表

这里用到了前面在链表中插入结点的insert()函数,在考试时需要将insert()函数写上

node* head_insert(int A[],int n){
	//将数组A中的元素以头插法的形式插入链表中
	//返回链表的头结点
	
	node *head=new node;//头结点 
	head->next=NULL; //一开始链表中没有元素 
	
	for(int i=0;i<n;i++){
		//由于是头插法,所以在头结点后面插入一个结点
		insert(head,A[i]); 
	}
	 
	return head; //返回链表的头结点 
} 

尾插法建立单链表

这里用到了前面在链表中插入结点的insert()函数,在考试时需要将insert()函数写上

node* tail_insert(int A[],int n){
	//将数组A中的元素以尾插法的形式插入链表中
	//返回链表的头结点
	
	node *head=new node;//头结点 
	head->next=NULL; //一开始链表中没有元素 
	node *tail=head; //尾指针 
	
	for(int i=0;i<n;i++){
		insert(tail,A[i]);//由于是尾插法,所以在尾结点后面插入一个结点  
		tail=tail->next;//更新尾指针的值 
	}
	
	return head; //返回头结点 
} 

链表元素逆置

采用头插法的方法,将链表中原来的结点一个个摘下来放入新的链表中

模板1

void reverse(node *head){
	//将链表中的元素逆置 
	
	node *head2=(node*)malloc(sizeof(node));//新链表的头结点
	//node *head2=new node;
	head2->next=NULL;
	
	//每次摘下原链表的第一个结点 
	while(head->next!=NULL){ //原链表中还有结点 
		 
		 node *p=head->next;//将第一个结点摘下
		 head->next=head->next->next;//原链表接上后面的结点 
		 
		 //以头插法将p结点插入新链表中
		 p->next=head2->next;
		 head2->next=p;
		 
	} 
	
	head->next=head2->next; //将原先的头结点指向新的链表 
	free(head2);//因为已经将原先的头结点指向新的链表,所以head2就没用了 
	//delete head2;
}

模板2

用到前面的insert()和del()函数,考试时需要写上

void insert(node *p,node *q){
	//在p指向结点的后面插入一个结点q 
	
	q->next=p->next;
	p->next=q;
}

node* del(node *p){
	//删除p的后一个结点,并将该结点返回 
	//这里不考虑q为NULL的情况 
	
	node *q=p->next;//q为要删除的结点 
	p->next=p->next->next; 
	
	return q; //将从链表中删除的结点返回 
}

void reverse(node *head){
	//将链表中的元素逆置 
	
	node *head2=(node*)malloc(sizeof(node));//新链表的头结点
	//node *head2=new node;
	head2->next=NULL;
	
	//每次摘下原链表的第一个结点 
	while(head->next!=NULL){ //原链表中还有结点 
		 node *p=del(head);//将第一个结点摘下
		 insert(head2,p);//以头插法将p结点插入新链表中
	} 
	
	head->next=head2->next; //将原先的头结点指向新的链表 
	free(head2);//因为已经将原先的头结点指向新的链表,所以head2就没用了 
	//delete head2;
}

获取链表中间结点(双指针法,快慢指针)

node* get_mid(node *head){
	//获取链表的中间结点,双指针法
	node *p=head;//快指针
	node *q=head;//慢指针
	
	while(p!=NULL && p->next!=NULL){
		//p不为空结点且p不是最后一个结点
		
		//快指针p走两步
		p=p->next;
		p=p->next;
		
		//慢指针走一步
		q=q->next; 
	} 
	
	//p走到末尾时,q刚好在中间位置 
	return q;
} 

双链表

双链表结点结构体

struct node{
	int data; //数据域 
	node *pre; //指向前一个结点的指针 
	node *next; //指向后一个结点的指针 
};

双链表中插入结点

模板1

void insert(node *p,node *q){
	//在p结点后插入结点q 
	//以下顺序不唯一,只要不断链就行 
	q->next=p->next;
	q->pre=p;
	if(q->next!=NULL){
		q->next->pre=q;
	} 
	p->next=q;
}

模板2

void insert(node *p,node *q){
	node *r=p->next;//r可能指向NULL 
	//以下顺序任意 
	p->next=q;
	q->pre=p;
	q->next=r;
	if(r!=NULL){
		r->pre=q;
	}
}

双链表中删除结点

模板1

node* del(node *p){
	//将p结点后面的结点从链表中删除,并将删除的结点返回
	//这里不考虑p后面结点为NULL的情况 
	
	node *q=p->next; //q为要删除的结点 
	p->next=p->next->next;
	if(q->next!=NULL){
		q->next->pre=p;
	}
	return q;//将链表中删除的结点返回 
}

模板2

node* del(node *p){
	//将p结点后面的结点从链表中删除,并将删除的结点返回
	//这里不考虑p后面结点为NULL的情况 
	node *q=p->next;
	node *r=q->next;//r可能指向NULL
	p->next=r;
	if(r!=NULL){
		r->pre=p;
	}
	return q; 
}

双链表的遍历

参考单链表的遍历

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值