前言
本篇文章主要接着上文的双向链表的创建与遍历(c++实现)
双向链表插入节点
在双向链表中插入新节点与单向链表相似,而根据新节点插入位置的不同,分为三种不同处理方式具体分析如下:
1.当在链表头部插入节点,只需把新节点的右指针指向链表原来的第一个节点,再把原链表头左指针指向新节点即可,
用代码描述:
insertnode->right= head;
head->left = insertnode;
head = insertnode;
2.当在链表中间位置插入新节点,例如在A和B之间,则需将A节点的右指针指向新节点,新节点的右指针指向B节点,B节点的左指针指向新节点,新节点的左指针指向A节点,
用代码描述:
A->right->left = insertnode;
insertnode->right = A->right;
insertnode->left = A;
A->right = insertnode;
3.当在链表尾插入新节点时,将原链表最后一个节点的右指针指向新节点,新节点的左指针指向原链表最后一个节点,且新节点的右指针指向NULL,
用代码描述:
ptr->right = insertnode;
insertnode->left = ptr;
insertnode->right = NULL;
实现代码
link InsertNode(link head,int position_data,int data){
link phead = new node;
phead = FindNode(head,position_data);
link insertnode = new node;
if(!insertnode) return NULL;
insertnode->data = data;
insertnode->right = NULL;
insertnode->left = NULL;
if(phead->right == NULL){//插入最后一个节点
insertnode->left = phead;
phead->right = insertnode;
}
else{ //插入中间节点
insertnode->right = phead->right;
phead->right->left = insertnode;
phead->right = insertnode;
insertnode->left = phead;
}
return head;
}
双向链表删除节点
插入新节点同样分为三种情况,分别进行操作:
1.当删除链表头的节点时,把头指针指向第二个节点即可,并释放第一个节点内存空间。
head = head->right;
head->left = NULL;
2.当删除中间节点时,将要删除节点的前一个节点的右指针指向要被删除节点的后一个节点,再将删除节点的后一个节点的左指针指向被删除节点的前一个节点,并释放内存空间。
del->left->right = del->right;
del->right->left = del->left;
3.当删除尾结点时,把指向最后一个节点之前的一个节点的右指针直接指向NULL,并释放内存空间即可。
ptr->left->right = NULL;
实现代码
if(head == phead){ //删除头结点
head = head->right;
head->left = NULL;
delete phead;
}
else{
if(phead->right == NULL){ //删除尾结点
phead->left->right = NULL;
delete phead;
}
else{
phead->left->right = phead->right;
phead->right->left = phead->left;
delete phead;
}
}
return head;
}
整个项目的完整代码
包括双向链表的创建、遍历、插入、删除。
#include<bits/stdc++.h>
using namespace std;
struct list1{
int data;
struct list1 *left,*right;
};
typedef struct list1 node;
typedef node *link;
void PrintList(link head){
link phead = new node;
phead = head;
cout<<"链表元素如下:(从头节点往右遍历): "<<endl;
while(phead!=NULL){
head = phead;
cout<<phead->data<<"->";
phead = phead->right; //phead按序往后遍历整个链表
if(!phead) cout<<"NULL"<<endl;
}
phead = head;
cout<<"链表元素如下:(从尾节点往左遍历): "<<endl;
while(phead!=NULL){
cout<<phead->data<<"->";
phead = phead->left;
head = phead;
if(!phead) cout<<"NULL"<<endl;
}
}
link CreateList(int a[],int n){
link head,phead,newnode;
head = new node;///建立头结点
if(!head) return NULL;
head->data = a[0];
head->right = NULL;
head->left = NULL;
phead = head;
for(int i = 1;i<n;i++){//建立链表
newnode = new node;
newnode->data = a[i];
newnode->right = NULL;
newnode->left = NULL;
phead->right = newnode;
newnode->left = phead;
phead = newnode;
}
return head;
}
link FindNode(link head,int position_data){
link phead;
phead = head;
while(phead != NULL){
if(phead->data == position_data)return phead;
phead = phead->right;
}
return phead;
}
link InsertNode(link head,int position_data,int data){
link phead = new node;
phead = FindNode(head,position_data);
link insertnode = new node;
if(!insertnode) return NULL;
insertnode->data = data;
insertnode->right = NULL;
insertnode->left = NULL;
if(phead->right == NULL){//插入最后一个节点
insertnode->left = phead;
phead->right = insertnode;
}
else{ //插入中间节点
insertnode->right = phead->right;
phead->right->left = insertnode;
phead->right = insertnode;
insertnode->left = phead;
}
return head;
}
link DeleteNode(link head,int position_data){
link top = head; //保留头指针
link phead = FindNode(head,position_data);
if(head == phead){ //删除头结点
head = head->right;
head->left = NULL;
delete phead;
}
else{
if(phead->right == NULL){ //删除尾结点
phead->left->right = NULL;
delete phead;
}
else{
phead->left->right = phead->right;
phead->right->left = phead->left;
delete phead;
}
}
return head;
}
int main(){
int position_data,data;
link head,phead;
int n;
cout<<"请输入初始链表元素个数: "<<endl;
cin>>n;
int a[n];
cout<<"请依次输入链表元素: ";
for(int i = 0;i<n;i++) cin>>a[i];
head = CreateList(a,n);
PrintList(head);
cout<<"请输入预插入位置之前的元素和要插入的元素(例:5 8): ";
cin>>position_data>>data;
head = InsertNode(head,position_data,data);
cout<<"插入之后的";
PrintList(head);
cout<<"请输入想删除的链表元素: ";
cin>>position_data;
head = DeleteNode(head,position_data);
cout<<"删除之后的";
PrintList(head);
return 0;
}
对上面代码中出现的函数做简单讲解:
FindNode()方法通过头结点和要查询的数据,遍历链表并返回预查询数据的节点;
CreateList()通过用户输入的数组创建一个链表;
InsertNode()插入新节点;
DeleteNode()删除指定节点;
PrintList()通过传入的链表头指针遍历整个链表数据并输出(双向链表分为两个方向进行)。
运行截图
总结
本文完成的代码只作为双向链表创建、遍历、插入、删除的简单实例,分别插入、删除了一次,读者也可自行添加判断语句通过输入来控制是插入还是删除,且本文代码所设前提为链表内数据唯一,即没有两个相同的数据,如果考虑数据不唯一,则增加了难度,不便于初学者理解链表的插入、删除节点。同时,没有考虑其他更多的意外情况,例如:用户输入要删除的元素,实际链表中不存在;这些操作需要在具体使用时再根据调整。
作者水平有限,旨在记录自己的学习过程,大家发现有什么错误或者建议尽可提出。