-
双向链表概念
- 概念
双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点
- 结点图解
- 链表图解
-
双向链表初始化
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int Status;
typedef int ElemType;
typedef struct Node {
struct Node * prior;
ElemType data;
struct Node * next;
} Node;
typedef struct Node *LinkList;
//双向链表操作(含有头结点)(也可以不设置头结点,但是在插入的时候就需要多判断插入的位置是不是1 是的话需要特殊判断)
Status createLinkList(LinkList *L){
int number;
LinkList temp = NULL;
LinkList target = NULL;
printf("可输入一个数值用于插入懂啊链表,输入0跳出循环\n");
//向链表中插入数据
while(1){
scanf("%d",&number);
if(number == 0) break;
if(*L == NULL){
//列表是NULL
//1.创建一个头结点
//2.创建一个新的节点
//3.头结点的next指向新节点
//4.头结点的prior指向null
//5.新节点的prior指向头结点
//6.新节点的next指向null
*L = (LinkList)malloc(sizeof(Node));
if(L == NULL) exit(0);
(*L)->next = NULL;
(*L)->prior = NULL;
temp = (LinkList)malloc(sizeof(Node));
if(temp == NULL) exit(0);
temp->data = number;
temp->prior = *L;
(*L)->next = temp;
temp->next = NULL;
}else{
//列表不是NULL
//1.创建一个新的节点
//2.找到尾节点
//3.新节点的next指向NULL
//4.新节点的prior指向尾结点
//5.尾节点的next 指向新节点
temp = (LinkList)malloc(sizeof(Node));
if(temp == NULL) exit(0);
for(target = *L; target->next != NULL; target = target->next);
temp->data = number;
temp->prior = target;
temp->next = NULL;
target->next = temp;
}
}
return OK;
}
//记录尾结点,下一次插入的时候不需要遍历查找尾结点
Status createLinkList2(LinkList *L){
int number;
LinkList temp = NULL;
LinkList lastNode = NULL;
printf("可输入一个数值用于插入懂啊链表,输入0跳出循环\n");
while (1) {
scanf("%d",&number);
if(number == 0) break;
if(*L == NULL){
//列表是NULL
//1.创建一个新的节点
//2.节点的next指向NULL
//3.节点的prior指向NULL
//4.lastNode = *L
*L = (LinkList)malloc(sizeof(Node));
if(*L == NULL) exit(0);
(*L)->data = number;
(*L)->next = NULL;
(*L)->prior = NULL;
lastNode = *L;
}else{
//列表不是NULL
//1.创建一个新的节点
//2.新节点的next指向NULL
//2.新节点的prior指向lastNode
//3.lastNode->next 指向新节点
//4.lastNode等于新节点
temp = (LinkList)malloc(sizeof(Node));
if(temp == NULL) exit(0);
temp->data = number;
temp->next = NULL;
temp->prior = lastNode;
lastNode->next = temp;
lastNode = temp;
}
}
return OK;
}
-
双向链表插入
//插入元素
//1.找到插入位置的前驱节点target
//2.创建一个新节点temp并赋值
//3.temp->next指向target->next
//4.target->next->prior指向temp
//5.target->next指向temp
//6.temp->prior 指向target
Status insert(LinkList *L,int item, int place){
if(*L == NULL) return ERROR;
if(place < 1) return ERROR;
LinkList temp = NULL;
LinkList target = NULL;
temp = (LinkList)malloc(sizeof(LinkList));
temp->data = item;
temp->prior = NULL;
temp->next = NULL;
if(temp == NULL) return ERROR;
int i;
for (i = 0, target = *L; i != place-1 && target != NULL; i++,target = target->next);
if(i != place - 1) return ERROR;
if(target == NULL) return ERROR;
if(target->next){
//插入位置是最后一个元素则不用修改target->next的prior指针
//和temp的next指针
target->next->prior = temp;
temp->next = target->next;
}
target->next = temp;
temp->prior = target;
return OK;
}
-
双向链表删除
//1.找到删除位置的前驱节点target
//2.创建temp指向target->next
//3.target->next指向temp->next
//4.temp->next->prior指向target
//4.free(temp)
Status delete(LinkList *L,int place){
if(*L == NULL) return ERROR;
if(place < 1) return ERROR;
LinkList target = NULL;
LinkList temp = NULL;
int i;
for (i = 0, target = *L; i != place-1 && target != NULL; i++,target = target->next);
if(i != place - 1) return ERROR;
if(target == NULL || target->next == NULL) return ERROR;
temp = target->next;
//如果删除的是尾结点 不需要修改temp->next 的prior结点的指向
if(temp->next){
temp->next->prior = target;
target->next = temp->next;
}else{
target->next = NULL;
}
free(temp);
return OK;
}
-
遍历、修改、查找
//遍历列表
void traverseList(LinkList L){
if(L == NULL) return;
LinkList temp = L->next;
do{
printf("%d ",temp->data);
temp = temp->next;
}while (temp != NULL);
printf("\n");
return;
}
//修改内容
Status modify(LinkList *L, int place, ElemType e){
if(place < 1) return ERROR;
if(!*L) return ERROR;
LinkList temp = NULL;
int i = 1;
for (temp = (*L)->next; temp != NULL; temp = temp->next) {
if(i == place){
temp->data = e;
return TRUE;
}
i++;
}
return FALSE;
}
//查找内容
Status getElem(LinkList L, int place, ElemType *e){
LinkList temp = NULL;
int i = 1;
for (temp = L->next; temp != NULL; temp = temp->next) {
if(i == place){
(*e) = temp->data;
return OK;
}
i++;
}
return ERROR;
}