双链表
基于C++的简单实现双链表
本人是个新人,如果有什么专业术语或者代码问题请联系我,谢谢!
文章目录
1.创建双链表结构体,并初始化双链表
typedef struct Node
{
int data;//保存数据
struct Node* prev;//指向前一个节点
struct Node* next;//指向后一个节点
}Node;
//创建链表的全局变量,因为后续的函数都需要使用到双链表,创建全局变量,方便使用链表
//后续函数使用链表时,就不需要传链表的参数就可以直接使用了
Node* head;
int main()
{
//初始化链表
head = NULL;
}
2.新建节点
Node *createNode(int value)
{
//创建节点
//相当于c语言中的Node* newNode = (Node*)malloc(sizeof(Node));
//这样写更简便
Node* newNode = new Node();
if(newNode == NULL)
{
printf("创建节点失败,内存不足!\n");
return NULL;
}
//代码执行到这表示节点创建成功
newNode->data = value;
newNode->prev = NULL;
newNode->next = NULL;
return newNode;
}
3.在链表头部插入数据
关键:最后头节点都要变为新创建的节点
void InsertAtHead(int value)
{
Node* newNode = createNode(value);
if(newNode == NULL)//代表内存不足,没有创建空间
{
printf("创建节点失败,内存不足!\n");
return;
}
//代码执行到这,表示可以将节点插入链表中
//如果链表为空,那么直接将头节点赋值为新节点
if(head == NULL)
{
head = newNode;
printf("插入节点成功!\n");
return;
}
//如果链表不为空,那么将新节点的下一个节点赋值为头节点,并将头节点的前一个节点指向新节点
newNode->next = head;
head->prev = newNode;
head = newNode;
printf("插入节点成功!\n");
return;
}
4.在链表尾部插入数据
void InsertAtTail(int value)
{
Node* newNode = createNode(value);
if(newNode == NULL)//代表内存不足,没有创建空间
{
printf("创建节点失败,内存不足!\n");
return;
}
//代码执行到这,表示可以将节点插入链表中
//如果链表为空,那么直接将头节点赋值为新节点
if(head == NULL)
{
head = newNode;
printf("插入节点成功!\n");
return;
}
//如果链表中有数据,则遍历链表,找到最后一个节点
//创建一个临时节点,进行遍历
Node* temp = head;
while(temp->next)//代表temp->next != NULL
{
temp = temp->next;
}
//代码运行到这,表示已经找到了最后一个节点
//可以进行插入操作
//将最后一个节点的下一个节点指向新节点,新节点的前一个节点指向最后一个节点
newNode->prev = temp;
temp->next = newNode;
printf("插入数据成功!\n");
}
5.正向打印链表
void PrintList()
{
printf("该双向链表为: ");
Node *temp = head;
while(temp)
{
printf("%d -> ",temp->data);
temp = temp -> next;
}
printf("NULL\n");
}
6.反向打印链表
void ReversePrint()
{
//先找到链表的尾部,再通过prev节点,将数据反向打印出来
Node* temp = head;
while(temp)
{
temp = temp->next;
}
printf("该双向链表反转后为:");
//代码执行到这,表示已经找到了链表中最后为NULL的节点,所以我们一开始打印的数据为该节点的前一个节点
temp = temp->prev;
while(temp)
{
printf("%d -> ",temp->data);
temp = temp->prev;
}
printf("NULL\n");
}
7.计算链表的长度
int ListLength()
{
//定义一个变量用来表示指向的节点
int count = 0;
Node *temp = head;
while(temp)
{
count++;
temp = temp->next;
}
return count;
}
8.删除指定位置的节点
//第一个参数表示要删除节点的位置
//第二个参数表示返回该节点位置的元素
bool DelNode(int index,int &e)
{
//判断链表是否为空
if(head == NULL)
{
printf("删除失败,该链表为空!\n");
return false;
}
//判断位置是否合法
int len = ListLength();
if(index < 1 || index > len)
{
printf("删除失败,该链表中没有该位置!\n");
return false;
}
//代码运行到这表示位置合法,链表不为空,可进行删除操作
Node* temp = head;
//若删除的是头节点,则需要将头节点的下一个节点设置为头节点
if(index == 1)
{
//将链表中的数据返回
e = temp->data;
head = temp->next;
if(temp->next != NULL)//代表链表不是只有一个节点,需要将下一个节点的prev设置为空
{
temp->next->prev = NULL;
}
//释放空间,避免内存泄漏
//因为我是用c++的new关键字创建的节点,所以需要用delete来释放内存
delete temp;//相当于c语言中的free(temp)
printf("删除节点成功!\n");
return true;
}
//寻找要删除位置的前一个节点
for(int i=0; i<index-2;i++)
{
temp = temp->next;
}
//代码运行到这表示找到了要删除位置的前一个节点
Node* delNode = temp->next;
//返回要删除节点位置的值
e = delNode->data;
temp -> next = delNode -> next;
if(temp->next != NULL)//代表要删除的不是最后一个节点
{
//则需要将要删除节点的后一个节点的prev指向要删除节点的前一个节点
delNode->next->prev = temp;
}
//释放内存
delete delNode;
printf("删除节点成功!\n");
return true;
}
9.在链表中查找数据
//在链表中查找数据
int GetItem(int value)
{
//对链表进行非空判断
if(head == NULL)
{
printf("查找失败,该链表为空表!\n");
return -1;
}
//定义一个变量用来表示当前指向的节点位置
int index = 0;
Node* temp = head;
while(temp)
{
index++;
if(temp->data == value)
{
return index;//表示在链表中的该位置找到了该值
}
temp=temp->next;
}
//表示链表中没有该值
printf("删除失败,链表中没有该值!\n");
return -1;
}
10.对函数功能的测试以及主函数
//测试在头部插入数据和正向打印数据
void test1()
{
// 在链表头部插入一些数据
for (int i = 0; i < 5; i++)
{
InsertAtHead(i*i);
}
PrintList();
}
//测试在尾部插入数据和逆向打印数据
void test2()
{
// 在链表尾部插入一些数据
for (int i = 0; i < 5; i++)
{
InsertAtTail(i * i);
}
ReversePrint();
}
//测试删除数据
void test3()
{
// 在链表头部插入一些数据
for (int i = 0; i < 5; i++)
{
InsertAtHead(i*i);
}
PrintList();
// 删除节点
int ele;
for (int i = 0; i < 5; i++)
{
DelNode(1, ele);
printf("删除节点位置的值位:%d\n", ele);
}
PrintList();
}
//测试查找数据
void test4()
{
// 在链表头部插入一些数据
for (int i = 0; i < 5; i++)
{
InsertAtHead(i*i);
}
PrintList();
int index = GetItem(0);
if(index>0)
{
printf("该值在链表中的第%d个位置上!\n",index);
}
}
// 创建链表
// 因为链表在所有函数都使用的到,直接创建全局变量,方便使用
Node *head;
int main()
{
// 初始化链表
head == NULL;
//test1();
//test2();
//test3();
test4();
return 0;
}