0
点赞
收藏
分享

微信扫一扫

王道考研——双链表、循环双链表

南柯Taylor 2022-05-02 阅读 66

代码实现—双链表

#include<iostream>
#include<stdlib.h> 
using namespace std;

typedef int ElemType;

typedef struct Dnode{
	ElemType data;//数据域
	struct Dnode * prior; //前驱指向 
	struct Dnode * next; //后驱指向 
}Dnode,*DLinkList;


/**
	初始化双链表 
*/

bool InitDLinkList(DLinkList &L) {
	L=(Dnode *)malloc(sizeof(Dnode)) ;//申请一个头结点 
	//初始化内存失败 
	if(L==NULL)return false;
	
	L->prior=NULL;//头结点的prior 永远指向NULL 
	L->next=NULL;
	
	return true;
}



/**
	双链表的插入 
	如果p结点是最后一个结点,则需要增加判断条件之后再执行3 
	以下四步,如果顺序乱了,会出现断链或者自己指向自己的情况
	比如1,4变成了4,1 
	 
*/
bool InsertByNextNode(Dnode *p,Dnode *s){
	
	if(p==NULL||s==NULL) return false;
	//1.结点s的后继指向为p的后继结点 
	s->next=p->next;
	//2.p的后继结点的前指向修改为s 
	if(p->next!=NULL)//当p不是最后一个结点时
		p->next->prior=s;
	//3.s的前指向更改为p 
	s->prior=p;
	//4.p的后继指向更改为s 
	p->next=s;
	
	return true;
}

/*
	s->next = p->next;
	p->next->prior = s;//要判断当前的p结点是不是最后一个结点 
	p->next = s;
	s->prior = p;
*/


/*前插,找到i-1,也可以后插*/
bool DListInsert(DLinkList &L, int i,ElemType e){
	if(i<1)	{
		cout<<"插入的位置有误!"<<endl;
		return false;
	}
	
	Dnode *p=L,*s;//从头结点开始遍历 
	int j=0;//从头结点开始遍历 
	while(p!=NULL&&j<i-1){
		p=p->next;
		j++;
	}
	
	s=(Dnode *)malloc(sizeof(Dnode)) ;
	s->data=e;
	InsertByNextNode(p,s);
}


/* 尾插法创建双链表 */
DLinkList CreateDList(DLinkList &L) {
	L=(Dnode *)malloc(sizeof(Dnode));//申请第一个结点 
	if(L!=NULL){
		L->prior=NULL; 
		L->next=NULL;
	}
	Dnode *s, *r=L;
	int x;
	cin>>x;
	while(x!=9999){
		s=(Dnode *)malloc(sizeof(Dnode));
		s->data=x;
		r->next=s;
		s->prior=r;//相比单链表,就多了一个指向r的前指针指向 
		r=s;
		cin>>x;
	}
	r->next=NULL;//最后一个结点指向为空
	
	return L; 
}

/*顺序打印双链表,跟单链表是一样的*/
void PrintByOrderASC(DLinkList &L){
	Dnode *p=L->next;//从第一个结点开始输出 
	while(p){//这样输出,导致当前的p可能为NULL 
		
		cout<<p->data<<" ";
		p=p->next;
	}
	cout<<endl;
}

/*逆序打印双链表,扫描到最后一个结点,再利用前驱结点倒回去*/
void PrintByOrderDESC(DLinkList &L){
	Dnode *p=L;
	while(p->next!=NULL){
		p=p->next;
	}
	
	while(p!=L){
		cout<<p->data<<" ";
		p=p->prior;
	}
	cout<<endl;
}

/*删除双链表的下一个结点*/
bool DeleteNextDnode(Dnode *p){
	if(p==NULL)return false;

	Dnode *q=p->next;//q为p的后继结点
	if(q==NULL)//如果q为空,即p为双链表的最后一个结点
		return false;
		
	//不为空则将p的后继结点更改为q的后继结点	
	p->next=q->next;
	if(q->next!=NULL) //如果q不为最后一个结点
		q->next->prior=p;// q的后继结点的前驱指向p结点 
		
	free(q) ;//释放q结点

	return true; 	
}

/* 销毁双链表 */
void DestoryDList(DLinkList &L){
	while(L->next!=NULL){
		DeleteNextDnode(L);
	}
	free(L)	;//释放头结点 
	L=NULL;//头指针指向NULL 
}

/*删除双链表的元素,并用e带回*/
bool DListDelete(DLinkList &L,int i,ElemType &e){
	if(i<1)	{
		cout<<"删除结点有误!" <<endl;
		return false;
	}
	Dnode *p=L;
	int j=0;//从头结点开始定位
	while(p!=NULL&&j<i-1) {
		p=p->next;
		j++;
	}
	
	//DeleteNextDnode(p);
	if(p==NULL)return false;//链表长为5,用户删除第7个元素,如果从第六个往后都为空 

	Dnode *q=p->next;//当前定位的结点,所要删除的结点 
	if(q==NULL)//如果q为空,即p为双链表的最后一个结点
		return false;
		
	//不为空则将p的后继结点更改为q的后继结点	
	p->next=q->next;
	if(q->next!=NULL) //如果q不为最后一个结点
		q->next->prior=p;// q的后继结点的前驱指向p结点 
	
	e=q->data;//带回所要删除的对象数据	
	free(q) ;//释放q结点
	return true;
	
}

int main(){
	DLinkList L;
	InitDLinkList(L);
	CreateDList(L);
	PrintByOrderASC(L);
	
	cout<<"在第3个位置插入3:";
	DListInsert(L,3,3);
	PrintByOrderASC(L);
	
	int e;
	DListDelete(L,5,e);
	cout<<"删除第五个结点,第五个结点的值为:"<<e<<endl;
	cout<<"顺序输出最后结果为:";
	PrintByOrderASC(L);
	cout<<"逆序输出最后结果为:";
	PrintByOrderDESC(L);
	
}


运行结果:
1 2 3 4 5 9999
1 2 3 4 5
在第3个位置插入3:1 2 3 3 4 5
删除第五个结点,第五个结点的值为:4
顺序输出最后结果为:1 2 3 3 5
逆序输出最后结果为:5 3 3 2 1
举报

相关推荐

0 条评论