【数据结构】单链表删除数据为x的元素(递归&非递归)

单链表删除元素时,可以按序号删除,也可以按数据删除。
这里写的是,不带头结点的单链表的按数据删除节点。

首先递归方式:

void Delete_x1(LinkList &L,int x){		//删除无头结点链表值为x的节点 
	LinkList p;							//递归删除 
	if(L==NULL)
		return ;
	if(L->data==x){				 
		p=L;				//让p指向了数据域与x相等的节点 
		L=L->next;			//指向值为x节点的指针直接指向了下一个节点 
		free(p);			//释放p节点,这里并不会断链 
		Delete_x1(L,x);
	}
	else
		Delete_x1(L->next,x);
}

第一次接触递归删除的时候肯定会觉得直接删除该节点了,那么链表是会断开的。
其实,在上面的写法中,链表是不会断开的。递归开始写明结束条件,L==NULL(这里是不带头结点的链表)。然后如果遇到值为x的节点了,需要删除。L=L->next;直接就把这个等于x的节点删除了,那么前面的链为什么不会断呢,因为这里的L就是上一个节点指向x的指针,现在直接把L指向了x的下一个,所以就不会断开了。
做个图了解一下:
在这里插入图片描述
然后是非递归方式:

void Delete_x2(LinkList &L,int x){		//非递归方法 
	LinkList p,q;
	LinkList pre;
	pre=(LinkList)malloc(sizeof(LNode));
	while(L->data==x){
		q=L;
		L=L->next;
		free(q);
	}
	p=L;
	pre->next=p;						//创建pre作为p的前驱指针 
	while(p!=NULL){
		if(p->data==x){	
			q=p;				
			pre->next=p->next;
			p=pre->next;
			free(q);
		}
		else{
			pre=p;
			p=p->next;
		}
	}
	return ;
}

这个没有头节点的就是麻烦一点,需要对第一个节点进行单独说明。现在知道引入头节点的好处了,首先如果删除的元素就在第一个的话,就需要直接删除,如果有多个的话就需要一直删一直删。
就上面这种写法的话会有一个问题,就是如果一个链表的所有值都是x的话,那么就会一直删一直删x.x.x.x.x…然后链表的每一个节点都被销毁了,然后链表就不存在了。
下面是大概的单链表的无头节点的一个框架:

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

typedef int ElemType;
typedef struct LNode{
	ElemType data;
	struct LNode *next;
}LNode,*LinkList;

LinkList InitList(LinkList &L){
	L=(LinkList)malloc(sizeof(LNode));
	//L->next=NULL;				//带头结点的单链表 
	L=NULL; 
	return L;
}

LinkList ListInsert_Head(LinkList &L,int n){
	LinkList p;
	p=new LNode;
	cin >> p->data;
	p->next=NULL;
	L=p;
	n--;
	while(n--){
		p=new LNode;
		cin >> p->data;
		p->next=L->next;
		L->next=p; 
	}
	return L;
}

LinkList ListInsert_Tail(LinkList &L,int n){
	LinkList p;
	LinkList r;
	p=new LNode;
	cin >> p->data;
	L=p;
	r=L;
	n--;
	while(n--){
		p=new LNode;
		cin >> p->data;
		p->next=NULL;
		r->next=p;
		r=p;
	}
	return L;
}

LinkList TraveList(LinkList &L){
	LinkList p;
	int length=0;
	p=L;
	while(p){
		cout << p->data << " ";
		p=p->next;
		length++;
	}
	cout << endl;
	cout << "The length is " << length << endl;
	return L;
}

void Delete_x1(LinkList &L,int x){		//删除无头结点链表值为x的节点 
	LinkList p;							//递归删除 
	if(L==NULL)
		return ;
	if(L->data==x){				 
		p=L;					//让p指向了数据域与x相等的节点 
		L=L->next;				//指向值为x节点的指针直接指向了下一个节点 
		free(p);				//释放p节点,这里并不会断链 
		Delete_x1(L,x);
	}
	else
		Delete_x1(L->next,x);
}
void Delete_x2(LinkList &L,int x){		//非递归方法 
	LinkList p,q;
	LinkList pre;
	pre=(LinkList)malloc(sizeof(LNode));
	while(L->data==x){
		q=L;
		L=L->next;
		free(q);
	}
	p=L;
	pre->next=p;						//创建pre作为p的前驱指针 
	while(p!=NULL){
		if(p->data==x){	
			q=p;				
			pre->next=p->next;
			p=pre->next;
			free(q);
		}
		else{
			pre=p;
			p=p->next;
		}
	}
	return ;
}

int  main()
{
	int n;
	LinkList L;
	while(true){
		InitList(L);
		cin >> n;
		ListInsert_Tail(L,n); 
		TraveList(L);
		int x;
		cin >> x;
		Delete_x2(L,x);
		TraveList(L);
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章