经过上一个文章单链表的实现,我决定写一个具有详细注释的双链表代码展示。
声明:本文章采用头结点方式,本文章结构先是代码分装函数,最后有全部代码实现
1. 定义创建并初始化
代码语言:javascript复制#include<stdio.h> //引用头文件
#include<stdlib.h>
#include<assert.h>
typedef struct Node //定义一个结构体
{
int data; //数据域
struct Node* per; //前指针域
struct Node* next; //后指针域三部分
}Node; //给结构体重新起一个名字
//创建并初始化
Node* initList() //返回的结点类型为Node*
{
Node* L = (Node*)malloc(sizeof(Node)); //动态开辟一个结点
assert(L); //判断L是否成功开辟,如果开辟失败直接报错
L->data = 0; //头结点的数据域来储存链表元素个数
L->per = 0;
L->next = 0; //两个指针置空
return L; //返回结点
}
2. 头插法添加结点
代码语言:javascript复制void headInsert(Node* L,int x)
{
Node* node = (Node*)malloc(sizeof(node)); //动态开辟一个结点
assert(node); //判断L是否成功开辟,如果开辟失败直接报错
node->data = x; //x是想插入的元素
if (L->data==0) //判断是否为第一次插入,如果为空进入if语句
{
node->next = NULL; //因为 为空与不为空操作步骤不一样
node->per = L;
L->next = node;
}
else
{ //不为空,
node->per = L;
node->next = L->next;
L->next->per = node;
L->next = node;
}
L->data ; //记录元素个数,加一
}
3. 尾插法添加结点
代码语言:javascript复制void tailList(Node* L, int x)
{
Node* n = L;
Node* node = (Node*)malloc(sizeof(Node));
assert(node);
node->data = x; //道理和上面代码类似,本处便不再解释
while (n->next) //循环遍历,作用:找到最后一个结点
{
n = n->next;
}
//找到会跳出循环,进行尾插
node->next = n->next; //先连接尾部
n->next = node;
node->per = n; //连接头部
L->data ; //记录长度元素个数加一
}
4. 删除任意位置结点
代码语言:javascript复制void deleteList(Node* L,int data)
{
Node* node = L->next;
if (node == NULL) //判断链表是否为空
{
printf("不存在");
exit(-1); //中断程序
}
while (node) //判断node结点是否为空指针
{
if (node->data == data) //找到后还要分两种情况
{
if (node->next == NULL) //第1种为尾结点
{
node->per->next = NULL;
node->per = NULL;
break; //跳出循环
}
node->next->per = node->per; //第2种不为尾结点
node->per->next = node->next;
}
node = node->next; //循环遍历,当node为空指针时跳出循环
}
free(node); //释放要删除的结点
node = NULL; //避免野指针出现
L->data--; //记录元素个数减一
}
5.打印链表
代码语言:javascript复制void printList(Node* L)
{
Node* node = L->next; //跳过头结点
while (node != NULL) //循环遍历每一个元素
{
printf("%d->", node->data);
node = node->next;
}
printf("NULLn"); //为了美观
}
6.主函数,来调用其它子函数
代码语言:javascript复制int main()
{
Node* L=initList();
headInsert(L, 1); //头插添加元素1
headInsert(L, 2); //头插添加元素2
tailList(L, 1); //头插添加元素1
tailList(L, 2); //头插添加元素2
printList(L); //打印链表
deleteList(L, 2); //删除元素为2的结点
deleteList(L, 1); //删除元素为1的结点
printList(L); //再打印链表
return 0;
}
整体代码
代码语言:javascript复制#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef struct Node
{
int data;
struct Node* per;
struct Node* next;
}Node;
//初始化
Node* initList()
{
Node* L = (Node*)malloc(sizeof(Node));
assert(L);
L->data = 0;
L->per = 0;
L->next = 0;
return L;
}
//头插法
void headInsert(Node* L,int x)
{
Node* node = (Node*)malloc(sizeof(node));
assert(node);
node->data = x;
if (L->data==0)
{
node->next = NULL;
node->per = L;
L->next = node;
L->data ;
}
else
{
node->per = L;
node->next = L->next;
L->next->per = node;
L->next = node;
}
L->data ; //记录元素个数
}
//尾插法
void tailList(Node* L, int x)
{
Node* n = L;
Node* node = (Node*)malloc(sizeof(Node));
assert(node);
node->data = x;
while (n->next)
{
n = n->next;
}
node->next = n->next;
n->next = node;
node->per = n;
L->data ;
}
//删除
void deleteList(Node* L,int data)
{
Node* node = L->next;
if (node == NULL)
{
printf("不存在");
exit(-1);
}
while (node)
{
if (node->data == data)
{
if (node->next == NULL)
{
node->per->next = NULL;
node->per = NULL;
break;
}
node->next->per = node->per;
node->per->next = node->next;
}
node = node->next;
}
free(node);
node = NULL;
L->data--;
}
//打印
void printList(Node* L)
{
Node* node = L->next;
while (node != NULL)
{
printf("%d->", node->data);
node = node->next;
}
printf("NULLn");
}
int main()
{
Node* L=initList();
/*headInsert(L, 1);
headInsert(L, 2);
tailList(L, 1);
tailList(L, 2);
printList(L);
deleteList(L, 2);*/
deleteList(L, 1);
printList(L);
return 0;
}
所有注释都是我亲自写的,如果文章对您有帮助,别吝啬您的手指嘿,嘿嘿嘿,谢谢大家,热烈欢迎大家评论!!