目录
前插操作(由于有前驱结点,所以可以直接前插,不需要写这么复杂)
今天复习双链表,以前复习的时候只看了带头结点的,今天居然发现不带头结点的不会写
双链表的定义(两种都一样)
typedef struct DNode
{
int data;
struct DNode *prior,*next;
}DNode,*DLinkList;
不带头结点的双链表
初始化
由于不带头结点,所以初始化只有头指针
bool InitList(DLinkList &L)
{
L=NULL;
return true;
}
头插操作(为链表赋值)
指的是在头指针所指结点之前插入元素(带头结点是在头结点之后插入)
当链表为空时,插入第一个节点需要特判,因为插入的结点的后继结点为空
void InsertList(DLinkList &L,int x) //头插:在头指针所指结点之前插入元素
{
DNode *p=new DNode;
p->data=x;
if(L==NULL) //特殊处理第一个节点
{
p->next=NULL;
p->prior=L;
L=p;
//L=p;
//p->next=NULL;
//p->prior=NULL;
}
else
{
p->next=L;
L->prior=p;
p->prior=NULL; //插入的为首元素,prior指针指向NULL
L=p;
}
}
一直头插就可以将数据逆序读入
插入操作(后插操作)
bool InsertAfterNode(DNode *p,int x) //在p结点之后插入元素,值为x
{
DNode *q=new DNode;
if(q==NULL) return false;
q->data=x;
q->next=p->next;
p->next->prior=q;
q->prior=p;
p->next=q;
return true;
}
前插操作(由于有前驱结点,所以可以直接前插,不需要写这么复杂)
单链表由于只有后继结点,方便实现后插,但不方便前插,所以单链表要想实现前插,才需要写这么复杂
bool InsertBehindNode(DNode *p,int x) //在p结点之前插入元素,值为x
{
DNode *q=new DNode;
if(q==NULL) return false;
q->data=p->data;
p->data=x; //依旧是后插,只是将插入结点的值赋为前结点p的值,p的值为插入元素的值
q->next=p->next;
p->next->prior=q;
q->prior=p;
p->next=q;
return true;
}
删除操作(删除当前结点)
bool Delete(DNode *p) //删除p结点
{
p->prior->next=p->next;
delete p;
}
查找第i个结点
DNode* Find(DLinkList L,int i) //查找第i个结点
{
int j=1;
DNode *p=L;
while(p!=NULL&&j<i)
{
p=p->next;
j++;
}
return p;
}
总结
主要是头插法插入的位置头指针所指元素之前,进而让头指针指向新插入的结点,而不是头指针之后(话术有问题),更不是头结点之后
完整代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n;
typedef struct DNode
{
int data;
struct DNode *prior,*next;
}DNode,*DLinkList;
bool InitList(DLinkList &L)
{
L=NULL;
return true;
}
void InsertList(DLinkList &L,int x) //头插:在头指针所指节点之前插入元素
{
DNode *p=new DNode;
p->data=x;
if(L==NULL) //特殊处理第一个节点
{
// p->next=NULL;
// p->prior=L;
// L=p;
L=p;
p->next=NULL;
p->prior=NULL;
}
else
{
p->next=L;
L->prior=p;
p->prior=NULL;
L=p;
}
}
DNode* Find(DLinkList L,int i) //查找第i个结点
{
int j=1;
DNode *p=L;
while(p!=NULL&&j<i)
{
p=p->next;
j++;
}
return p;
}
bool InsertAfterNode(DNode *p,int x) //在p结点之后插入元素,值为x
{
DNode *q=new DNode;
if(q==NULL) return false;
q->data=x;
q->next=p->next;
p->next->prior=q;
q->prior=p;
p->next=q;
return true;
}
bool InsertBehindNode(DNode *p,int x) //在p结点之前插入元素,值为x
{
DNode *q=new DNode;
if(q==NULL) return false;
q->data=p->data;
p->data=x; //依旧是后插,只是将插入结点的值赋为前结点p的值,p的值为插入元素的值
q->next=p->next;
p->next->prior=q;
q->prior=p;
p->next=q;
return true;
}
bool Delete(DNode *p) //删除p结点
{
p->prior->next=p->next;
delete p;
}
void PrintList(DLinkList L)
{
DNode *p=L;
while(p!=NULL)
{
cout<<p->data<<" ";
p=p->next;
}
cout<<endl;
}
signed main()
{
freopen("A.txt","r",stdin);
cin>>n;
DLinkList L;
InitList(L);
while(n--)
{
int x; cin>>x;
InsertList(L,x);
}
PrintList(L);
DNode *p=Find(L,3);
InsertAfterNode(p,5);
PrintList(L);
InsertBehindNode(p,5);
PrintList(L);
Delete(p);
PrintList(L);
return 0;
}
带头结点的双链表
初始化
bool InitList(DLinkList &L)
{
L=new DNode; //创建头指针
if(L==NULL) return false;
L->next=NULL; //头指针前驱和后继要置为NULL,区别于不带头结点的双链表
L->prior=NULL;
return true;
}
头插操作(为链表赋值)
void InsertList(DLinkList &L,int x) //头插:在头指针所指节点之前插入元素
{
DNode *p=new DNode;
p->data=x;
if(L->next==NULL) //特殊处理第一个节点
{
p->next=NULL;
p->prior=L->next;
L->next=p;
}
else
{
p->next=L->next;
L->next->prior=p;
p->prior=L->next;
L->next=p;
}
}
前插操作,后插操作,删除操作
和前面一样
查找第i个结点
DNode* Find(DLinkList L,int i) //查找第i个结点
{
int j=1;
DNode *p=L->next;
while(p!=NULL&&j<i)
{
p=p->next;
j++;
}
return p;
}
完整代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n;
typedef struct DNode
{
int data;
struct DNode *prior,*next;
}DNode,*DLinkList;
bool InitList(DLinkList &L)
{
L=new DNode;
if(L==NULL) return false;
L->next=NULL;
L->prior=NULL;
return true;
}
void InsertList(DLinkList &L,int x) //头插:在头指针所指节点之前插入元素
{
DNode *p=new DNode;
p->data=x;
if(L->next==NULL) //特殊处理第一个节点
{
p->next=NULL;
p->prior=L->next;
L->next=p;
}
else
{
p->next=L->next;
L->next->prior=p;
p->prior=L->next;
L->next=p; //相当于是插入一个
}
}
DNode* Find(DLinkList L,int i) //查找第i个结点
{
int j=1;
DNode *p=L->next;
while(p!=NULL&&j<i)
{
p=p->next;
j++;
}
return p;
}
bool InsertAfterNode(DNode *p,int x) //在p结点之后插入元素,值为x
{
DNode *q=new DNode;
if(q==NULL) return false;
q->data=x;
q->next=p->next;
p->next->prior=q;
q->prior=p;
p->next=q;
return true;
}
bool InsertBehindNode(DNode *p,int x) //在p结点之前插入元素,值为x
{
DNode *q=new DNode;
if(q==NULL) return false;
q->data=p->data;
p->data=x; //依旧是后插,只是将插入结点的值赋为前结点p的值,p的值为插入元素的值
q->next=p->next;
p->next->prior=q;
q->prior=p;
p->next=q;
return true;
}
bool Delete(DNode *p) //删除p结点
{
p->prior->next=p->next;
delete p;
}
void PrintList(DLinkList L)
{
DNode *p=L->next;
while(p!=NULL)
{
cout<<p->data<<" ";
p=p->next;
}
cout<<endl;
}
signed main()
{
freopen("A.txt","r",stdin);
cin>>n;
DLinkList L;
InitList(L);
while(n--)
{
int x; cin>>x;
InsertList(L,x);
}
PrintList(L);
DNode *p=Find(L,3);
InsertAfterNode(p,5);
PrintList(L);
InsertBehindNode(p,5);
PrintList(L);
Delete(p);
PrintList(L);
return 0;
}
总结
还是要多做总结,to be modest