有两个双向循环链表A,B,知道其头指针为:pHeadA,pHeadB,请写一个函数将两链表中数值相同的节点删除。
分析:
(1) 首先把A中含有与B中相同的数据节点找出来组成一个新的链表,例如:
链表A:1 2 3 4 2 6 4
链表B:10 20 3 4 2 10
新链表C:2 3 4
(2) 遍历链表C,删除A和B的所有和C中节点值相同的节点。
#include "stdafx.h"
#include <iostream>
//双向循环链表的操作
using namespace std;
typedef struct Dbnode{
int data; //节点数据
Dbnode *left; //前驱结点指针
Dbnode *right; //后继节点指针
}Dbnode;
void Print(Dbnode *head);
//根据数据创建节点
Dbnode *CreateNode(int data){
Dbnode *pnode=new Dbnode;//
if (pnode==NULL){ //如果内存申请失败,返回NULL
return NULL;
}
pnode->data=data;
pnode->left=pnode;//新节点的前驱和后继指针都指向自身
pnode->right=pnode;
return pnode;
}
//在表尾插入新节点,返回表头节点
Dbnode *AppendNode(Dbnode *head,int data){
if (head==NULL){
return NULL;
}
Dbnode *phead=head;
Dbnode *pnode=CreateNode(data);//创建一个新节点
while (head!=phead->right){ //找到表尾
phead=phead->right;
}
pnode->right=phead->right;//右连接
head->left=pnode;
phead->right=pnode;//左连接
pnode->left=phead;
return head;
}
//双向循环链表测长
int GetLength(Dbnode *head){
if (head==NULL)//如果指针为空则返回0
{
return 0;
}
Dbnode *phead=head->right;
int i=1;
while (head!=phead){
phead=phead->right;
i++;
}
return i;
}
//双向循环链表的节点查找
Dbnode *FindNode(Dbnode *head,int data){
if (head==NULL){
return NULL;
}
if (head->data==data){ //如果表头节点和值相等
return head;
}
Dbnode *phead=head->right;
while (head != phead && phead->data != data){
phead=phead->right;
}
if (phead->data==data){//如果是值相等退出,则返回节点
return phead;
}
else //如果没有找到,则返回NULL
return NULL;
}
//获得pA链表和pB链的交集,返回一个新链表
Dbnode *GetLink(Dbnode *pA,Dbnode *pB){
if (pA==NULL || pB==NULL){//如果为空,则返回NULL
return NULL;
}
Dbnode *pC=NULL;
Dbnode *node=NULL;
Dbnode *phead=NULL;
//Dbnode *pheadA=pA;
int len_a=GetLength(pA);
int len_b=GetLength(pB);
int data;
for (int i=0;i<len_a;i++){
phead=pB;
data=pA->data;
if (FindNode(pC,data)!=NULL){//如果data已在pC中,则进行下次循环
pA=pA->right;
continue;
}
if (data==pB->data){//如果pB的头节点和data相等
node=new Dbnode;
node->data=data;
node->left=node->right=node;
if (pC==NULL){//如果pC为空,则作为头节点
pC=node;
pC->left=pC;
pC->right=pC;
}else{
pC->right->left=node;
node->right=pC->right;
pC->right=node;
node->left=pC;
}
}else{//如果pB的头节点和data不相等
phead=pB->right;
while (pB!=phead && phead->data != data){
phead=phead->right;
}
if (phead->data == data){
node=new Dbnode;
node->data=data;
node->right=node;
node->left=node;
if (pC==NULL){ //如果pC为NULL
pC=node;
pC->left=pC;
pC->right=pC;
}else{
pC->right->left=node;
node->right=pC->right;
pC->right=node;
node->left=pC;
}
}
}
pA=pA->right;
}
return pC;
}
//删除节点中所有数值等于data的节点
Dbnode *DeleteNode(Dbnode *head,int data){
if (head==NULL){//链表不存在返回NULL
return NULL;
}
Dbnode *node=NULL;
Dbnode *pdelnode=NULL;
while(head->data==data){ //如果头节点相等,则删除
if (head->right==head){ //如果只有一个头节点,则返回NULL
delete head;
return NULL;
}
pdelnode=head; //保存即将删除的节点
node=head->right;//保存head的下一个节点
head->right->left=head->left;
head->left->right=head->right;
head=node;//head的下一个节点作为头节点
delete pdelnode;//释放删除的节点
pdelnode =NULL;
}
Dbnode *phead=head->right;
while (head!=phead){
if (phead->data==data){
while(phead->data==data){
pdelnode=phead;
node=phead->right; //保存phead的下一个节点
phead->right->left=phead->left;
phead->left->right=phead->right;
phead=node;
delete pdelnode;
pdelnode=NULL;
}
}else
phead=phead->right;
}
return head;
}
//删除链表A和链表B中所有含相同数据的节点
void DeleteEqual(Dbnode **pA,Dbnode **pB){
Dbnode *pheadA=*pA;
Dbnode *pheadB=*pB;
Dbnode *pheadC=NULL;
if (pA==NULL || pB==NULL){ //如果指针为NULL ,返回
return ;
}
if (pheadA==NULL || pheadB==NULL){//如果链表为空,返回
return;
}
Dbnode *pC=GetLink(pheadA,pheadB);//获得公共集合
if (pC==NULL){
return;
}
pheadA=DeleteNode(pheadA,pC->data);//删除pheadA和pheadB中和pC的头节点值相等的所有节点
pheadB=DeleteNode(pheadB,pC->data);
pheadC=pC->right;
while (pheadC!=pC){ //循环删除pheadA和pheadB中和pC的头节点值相等的所有节点
pheadA=DeleteNode(pheadA,pheadC->data);
pheadB=DeleteNode(pheadB,pheadC->data);
pheadC=pheadC->right;
}
*pA=pheadA;//把处理后的链表再分别赋给pA和pB
*pB=pheadB;
}
//打印双向循环链表
void Print(Dbnode *head){
if (NULL==head){ //head为NULL表示为空链表
getchar();
return;
}
cout<<head->data<<" "; //先打印出表头
Dbnode *p=head->right;
while (head!=p){ //依次遍历,直到到达表尾
cout<<p->data<<" ";
p=p->right;
}
cout<<endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
Dbnode *pA=NULL;
Dbnode *pB=NULL;
Dbnode *pC=NULL;
Dbnode *pheadC=pC;
Dbnode *pfind=NULL;
Dbnode *pNhead=NULL;
Dbnode *pList=NULL;
pA=CreateNode(0);//创建表头节点,表头节点不作为存放有意义数据的节点
for (int i=1;i<10;i++){
AppendNode(pA,i);
}
AppendNode(pA,9);
AppendNode(pA,20);
cout<<"pA:";
Print(pA);
pB=CreateNode(0);
AppendNode(pB,3);
AppendNode(pB,2);
AppendNode(pB,6);
AppendNode(pB,9);
AppendNode(pB,9);
AppendNode(pB,15);
AppendNode(pB,20);
AppendNode(pB,20);
cout<<"pB:";
Print(pB);
pC=GetLink(pA,pB);
cout<<"Subset pA and pB:";
Print(pC);
DeleteEqual(&pA,&pB);
cout<<"After DeleteEqual pA:";
Print(pA);
cout<<" After DeleteEqual pB:";
Print(pB);
system("pause");
delete [] pA;
delete [] pB;
delete [] pC;
return 0;
}
