双向链表的核心操作

版权声明:转载请注明出处 https://blog.csdn.net/doubleguy/article/details/83622369

循环链表在单链表的基础上加入指向前驱的指针prior,其大致实现几乎和单链表一样,核心区别就是插入删除不同。

这里就着重围绕插入和删除来写,其他功能可以自己实现一下。如果双向链表不太懂的话,说明单链表你没弄得很明白,可以看下我的单链表弄明白:https://blog.csdn.net/doubleguy/article/details/83384327

1.创建双向链表(后插法)

//后插法创建双向链表 
void CreateList(LinkList &l,int n){
	l = new LNode;
	l->next = NULL;
	LNode *r = l;
	for(int i=0;i<n;i++){
		LNode *p = new LNode;
		scanf("%d",&p->data);
		p->prior = r;
		r->next = p;
		r = r->next;
		p->next = NULL;
	}
}

2.查找 

这里注意一点,为了插入和删除的方便,我查找操作的返回值是指向要查找的位置的指针。举个例子,我调用GetElem(l,4)时,如果链表中有大于等于4位元素时它返回指向第4个元素位置的指针。它的好处可以在插入和删除中明显的看出来。

//查找
LNode *GetElem(LinkList l,int i){
	LNode *p = l->next;
	int j = 1;
	while(j<i&&p){
		p = p->next;
		j++;
	}
	while(!p||i<j){
		printf("输入越界!");
		return NULL;
	}
	return p;
} 

3.插入

直接调用GetElement()函数可以直接找到链表中第i个元素的位置指针,多方便啊!另外,这里的插入是在第i个位置前的一个元素插入。

//插入(在带头节点的双向链表l中第i个元素之前插入元素e)
Status ListInsert(LinkList &l,int i,int &e){
	LNode *p = NULL;
	if(!(p = GetElem(l,i)))
		return 0;
	LNode *r = new LNode;
	r->data = e;
	r->prior = p->prior;
	p->prior->next = r;
	r->next = p;
	p->prior = r;
	return 1;
}

 4.删除

注意调用GetElement()函数时,指针p是指向第i个元素的,需要讨论一个p->next是否指向空,也即是讨论一下删除的元素是否是最后一位。

//删除带头节点的双向链表l的第i个位置的元素
Status ListDelete(LinkList &l,int i){
	LNode *p = NULL;
	if(!(p = GetElem(l,i)))
		return 0;
	if(p->next != NULL){
		p->prior->next = p->next;
		p->next->prior = p->prior;
	}
	else
		p->prior->next = NULL;
	delete p;
	return 1;
}

完整代码如下:  

#include<cstdio>
#include<algorithm>
#include<stdlib.h>
#pragma execution_character_set("utf-8")
typedef int Status;
using namespace std;
typedef struct LNode{
	int data;
	struct LNode *prior;
	struct LNode *next;
}LNode,*LinkList;
 
Status InitList(LinkList &l){
	l = new LNode;
	return 1;
}
 
//后插法创建双向链表 
void CreateList(LinkList &l,int n){
	l = new LNode;
	l->next = NULL;
	LNode *r = l;
	for(int i=0;i<n;i++){
		LNode *p = new LNode;
		scanf("%d",&p->data);
		p->prior = r;
		r->next = p;
		r = r->next;
		p->next = NULL;
	}
}
 
//查找
LNode *GetElem(LinkList l,int i){
	LNode *p = l->next;
	int j = 1;
	while(j<i&&p){
		p = p->next;
		j++;
	}
	while(!p||i<j){
		printf("输入越界!");
		return NULL;
	}
	return p;
} 
 
//插入(在带头节点的双向链表l中第i个元素之前插入元素e)
Status ListInsert(LinkList &l,int i,int &e){
	LNode *p = NULL;
	if(!(p = GetElem(l,i)))
		return 0;
	LNode *r = new LNode;
	r->data = e;
	r->prior = p->prior;
	p->prior->next = r;
	r->next = p;
	p->prior = r;
	return 1;
}
 
//删除带头节点的双向链表l的第i个位置的元素
Status ListDelete(LinkList &l,int i){
	LNode *p = NULL;
	if(!(p = GetElem(l,i)))
		return 0;
	if(p->next != NULL){
		p->prior->next = p->next;
		p->next->prior = p->prior;
	}
	else
		p->prior->next = NULL;
	delete p;
	return 1;
}
 
//打印函数 
void PrintList(LinkList &l){
	LNode *p = l->next;
	if(!p){
		printf("表为空!");
		return;
	}
	while(p){
		printf("%d ",p->data);
		p = p->next;
	}
	printf("\n");
}
 
int main(){
	LinkList l;
	int n;
	int status;
	int e,loc;
	printf("请输入你想要创建的双向链表的长度n:");
	scanf("%d",&n);
	printf("请输入%d个数:",n);
	CreateList(l,3);
	printf("当前表中元素为:");
	PrintList(l);
	printf("请输入你要插入的位置和数值:");
	scanf("%d%d",&loc,&e);
	status = ListInsert(l,loc,e);
	if(status){
		printf("插入成功!\n当前表中元素为:");
		PrintList(l);
	}
	else
		printf("插入失败,输入越界!\n");
	printf("请输入你要删除数的位置:");
	scanf("%d",&loc);
	status = ListDelete(l,loc);
	if(status){
		printf("删除成功!\n当前表中元素为:");
		PrintList(l);
	}
	else
		printf("删除失败,输入越界!\n"); 
	return 0;
}

猜你喜欢

转载自blog.csdn.net/doubleguy/article/details/83622369