一、定义:
单链表:每一个节点都有一个直接后继,只能单方向查找元素
双向链表:每个节点既有直接前驱也有直接后继,一个指针域指向前驱,一个指针域指向后继
二、功能
双线链表结构体
cs
#ifndef __DOUBLE_LIST_H__
#define __DOUBLE_LIST_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int datatype;
typedef struct double_list{
union{
int len;
datatype data;
};
struct double_list *next;//指向后继指针
struct double_list *pri;//指向前驱指针
}double_list,*double_p;
//创建双向循环链表头节点
double_p creat_head();
//创建节点
double_p creat_node(datatype data);
//头插
void insert_head(double_p H,datatype data);
//尾插
void insert_tail(double_p H,datatype data);
//输出
void out_put(double_p H);
//按位置插入
void insert_pos(double_p H,int pos,datatype data);
//尾删
void del_tail(double_p H);
//头删
void del_head(double_p H);
//按位置删除
void del_pos(double_p H,int pos);
//判空
int empty_double(double_p H);
//释放双向链表
void free_double(double_p H);
#endif
1.创建双向链表头节点
cs
double_p creat_head(){
double_p H=(double_p)malloc(sizeof(double_list));
if(H==NULL){
printf("空间申请失败\n");
return NULL;
}
H->len=0;
H->next=NULL;
H->pri=NULL;
return H;
}
2.创建节点
cs
//创建节点
double_p creat_node(datatype data){
double_p new=(double_p)malloc(sizeof(double_list));
if(new==NULL){
printf("空间申请失败\n");
return NULL;
}
new->data=data;
return new;//返回申请节点的首地址
}
3.头插
cs
//头插
void insert_head(double_p H,datatype data){
if(H==NULL){
printf("空间申请失败\n");
return;
}
double_p new=creat_node(data);
if(H->next!=NULL){
new->pri=H;//新节点的前去指向头节点
H->next->pri=new;//头节点后继节点的前去指向新节点
//如果不判断H->next==NUL,H->next->pri会涉及到空指针的间接访问
new->next=H->next;//新节点的后继指向H的后继
H->next=new;//一定要最后写
H->len++;
}
else{
new->next=H->next;
H->next=new;
new->pri=H;
H->len++;
}
}
4.尾插
cs
//尾插
void insert_tail(double_p H,datatype data){
if(H==NULL){
printf("空间申请失败\n");
return;
}
double_p new=creat_node(data);
//找到最后一个节点
double_p p=H;
while(p->next!=NULL){
p=p->next;
}
new->pri=p;
new->next=p->next;
p->next=new;
H->len++;
}
5.按位置插入
cs
//按位置插入
void insert_pos(double_p H,int pos,datatype data){
if(H==NULL){
printf("空间申请失败\n");
return;
}
//位置合理性判断
if(pos<=0 || pos>H->len+1){
printf("位置不合理\n");
return;
}
//找到pos-1位置的节点
double_p p=H;
for(int i=0;i<pos-1;i++){
p=p->next;
}
double_p new=creat_node(data);
new->pri=p;//新节点的前驱指向pos-1
new->next=p->next;//新节点的后继指向原来pos-1的后继
if(p->next!=NULL){
p->next->pri=new;//如果pos位置本身有节点
//让pos节点的前驱指向新节点
}
p->next=new;//pos-1的后继指向新节点
H->len++;
}
6.输出
cs
//输出
void out_put(double_p H){
if(H==NULL){
printf("空间申请失败\n");
return;
}
double_p p=H->next;
while(p!=NULL){
printf("%d ",p->data);
p=p->next;
}
putchar(10);
}
7.尾删
cs
//尾删
void del_tail(double_p H){
if(H==NULL){
printf("空间申请失败\n");
return;
}
double_p p=H;
while(p->next->next!=NULL){
p=p->next;
}
double_p del=p->next;
p->next=p->next->next;
free(del);
H->len--;
}
8.头删
cs
//头删
void del_head(double_p H){
if(H==NULL){
printf("空间申请失败\n");
return;
}
double_p p=H->next;
double_p del=p;
H->next=p->next;
p->next->pri=H;
free(del);
H->len--;
}
9.按位置删除
cs
void del_pos(double_p H,int pos){
if(H==NULL){
printf("空间申请失败\n");
return;
}
if(pos<=0 || pos>H->len){
printf("位置不合理\n");
return;
}
double_p p=H;
for(int i=0;i<pos-1;i++){
p=p->next;
}
double_p del=p->next;
del->next->pri=p;
p->next=p->next->next;
free(del);
H->len--;
}
10.判空
cs
int empty_double(double_p H){
if(H==NULL){
printf("空间申请失败\n");
return -1;
}
return H->next==NULL?1:0;
}
11.释放双向链表
cs
//释放双向链表
void free_double(double_p H){
if(H==NULL){
printf("空间申请失败\n");
return;
}
if(empty_double(H)){
printf("链表为空\n");
return;
}
//循环头删
double_p p=H->next;
double_p del;
while(p!=NULL){
del=p;//让del指针保存每次要释放的指针
p=p->next;
free(del);
del=NULL;
}
}