今天是双链表建立以及结点的插入和删除
话不多说,直接上代码
打印链表定义和之前一样
void PrintList(DLinkList L) {
L = L->next;
while (L != nullptr) { //for循环遍历数组类型 while循环遍历其他类型
printf("%3d", L->data);
L = L->next;
}
printf("\n");
}
首先是结点定义,注意双链表的结点包含前后指针
typedef int ElemType ;
typedef struct DNode{
ElemType data ;
DNode *prior ,*next ; //定义前驱和后继指针
}DNode,*DLinkList ;
初始化双链表代码如下:
void InitDNode(DLinkList &L){ //初始化链表 建立头指针 DLinkList 和 DNode* 等价
L=(DNode *)malloc(sizeof(DNode));
L->prior= nullptr;
L->next= nullptr;
}
之后是头插法和尾插法建立链表
void list_head_insert(DNode *&L){ //头插法插入新元素
ElemType x ;
DNode *s ;
L=(DNode *)malloc(sizeof(DNode)) ; //LNode*是结构体指针 和 LinkList完全等价
L->prior= nullptr;
L->next= nullptr ;
scanf("%d" ,&x) ;
while (x!=9999){
s=(DLinkList)malloc(sizeof(DNode)) ; //LNode*是结构体指针 和 LinkList完全等价
s->data=x ;
s->next=L->next ;
if(L->next!= nullptr){ //插入第一个元素时,后结点的前指针不用返回
L->next->prior=s ;
}
s->prior=L ;
L->next=s ;
scanf("%d" ,&x) ;
}
}
void list_tail_insert(DNode *&L){ //尾插法插入新元素
ElemType x ;
L=(DNode *)malloc(sizeof(DNode)) ; //LNode*是结构体指针 和 LinkList完全等价
L->prior= nullptr;
L->next= nullptr ;
DNode *s,*r=L ; //指针r 必须在确定 L 前后指针之后定义,确保r的前后指针为空
scanf("%d" ,&x) ;
while (x!=9999){
s=(DNode *)malloc(sizeof(DNode)) ; //内部无须再次声明 s结点
s->data=x ;
r->next=s ;
s->prior=r ;
r=s ;
scanf("%d" ,&x) ;
}
r->next= nullptr ; //最终最后一个结点 后继 指向空
}
然后是删除结点定义:
void DNodeDelete(DLinkList &L ,ElemType x){
int len=0 ;
DNode *p=L->next ,*q=L ;
while (p!= nullptr && p->data!=x){ //用while或者for循环遍历元素,if只能执行一次
q=p ;
p=p->next ;
len++ ;//计数器原理
}
if(p!= nullptr && p->data==x){ //该if在循环外,否则找到对应元素后仍无法删除,执行while
q->next=p->next ;
if(p->next!= nullptr){
p->next->prior=q ;
}
free(p) ;
printf("该值在第%d位\n",len+1) ; //数组下标是len 所以位置应该是len+1
}else if(p== nullptr){
printf("链表没有该元素\n") ;
}
}
总体代码实现如下:
#include <stdio.h>
#include <stdlib.h> //malloc申请的头文件
typedef int ElemType ;
typedef struct DNode{
ElemType data ;
DNode *prior ,*next ; //定义前驱和后继指针
}DNode,*DLinkList ;
void InitDNode(DLinkList &L){ //初始化链表 建立头指针 DLinkList 和 DNode* 等价
L=(DNode *)malloc(sizeof(DNode));
L->prior= nullptr;
L->next= nullptr;
}
void list_head_insert(DNode *&L){ //头插法插入新元素
ElemType x ;
DNode *s ;
L=(DNode *)malloc(sizeof(DNode)) ; //LNode*是结构体指针 和 LinkList完全等价
L->prior= nullptr;
L->next= nullptr ;
scanf("%d" ,&x) ;
while (x!=9999){
s=(DLinkList)malloc(sizeof(DNode)) ; //LNode*是结构体指针 和 LinkList完全等价
s->data=x ;
s->next=L->next ;
if(L->next!= nullptr){ //插入第一个元素时,后结点的前指针不用返回
L->next->prior=s ;
}
s->prior=L ;
L->next=s ;
scanf("%d" ,&x) ;
}
}
void list_tail_insert(DNode *&L){ //尾插法插入新元素
ElemType x ;
L=(DNode *)malloc(sizeof(DNode)) ; //LNode*是结构体指针 和 LinkList完全等价
L->prior= nullptr;
L->next= nullptr ;
DNode *s,*r=L ; //指针r 必须在确定 L 前后指针之后定义,确保r的前后指针为空
scanf("%d" ,&x) ;
while (x!=9999){
s=(DNode *)malloc(sizeof(DNode)) ; //内部无须再次声明 s结点
s->data=x ;
r->next=s ;
s->prior=r ;
r=s ;
scanf("%d" ,&x) ;
}
r->next= nullptr ; //最终最后一个结点 后继 指向空
}
void DNodeDelete(DLinkList &L ,ElemType x){
int len=0 ;
DNode *p=L->next ,*q=L ;
while (p!= nullptr && p->data!=x){ //用while或者for循环遍历元素,if只能执行一次
q=p ;
p=p->next ;
len++ ;//计数器原理
}
if(p!= nullptr && p->data==x){ //该if在循环外,否则找到对应元素后仍无法删除,执行while
q->next=p->next ;
if(p->next!= nullptr){
p->next->prior=q ;
}
free(p) ;
printf("该值在第%d位\n",len+1) ; //数组下标是len 所以位置应该是len+1
}else if(p== nullptr){
printf("链表没有该元素\n") ;
}
}
void PrintList(DLinkList L) {
L = L->next;
while (L != nullptr) { //for循环遍历数组类型 while循环遍历其他类型
printf("%3d", L->data);
L = L->next;
}
printf("\n");
}
int main() { //双链表插入建立与删除
DLinkList (L) ;
printf("********************************************************************\n") ;
InitDNode(L) ;
list_head_insert(L) ;
PrintList(L) ;
printf("********************************************************************\n") ;
DNodeDelete(L,3) ;
PrintList(L) ;
printf("********************************************************************\n") ;
list_tail_insert(L);
PrintList(L) ;
printf("********************************************************************\n") ;
return 0;
}
若要对 1 2 3 4 9999和 5 6 7 8 9999操作(9999为结束标志)则会输出如下结果: