数据结构---带头结点的双向链表的增删查改1(C语言实现)
程序员文章站
2024-01-15 19:51:16
...
实现环境:LINUX
带头结点的增删查改相对而言比较简单,但是里边还是有些许坑,,稍不注意就掉进去,半天爬不出来。
将要实现的链表的图:
在双向链表中需要注意的是要注意两组指针的指向,即next和prev对应。双向链表已经可以说完成一半了。
在一个需要注意的坑是,在插入的时候需要注意的是一定要先new与node2然后在进行其他的操作,不然node1与node2之间指向断开,就会指向随机值,我就在这个坑了怕了一个多小时,才调试出来。
代码实现:
LinkList.c:
#include "LinkList.h"
#include<stdio.h>
#include<stdlib.h>
//实现创建
DLinkNode* DLinkListCreatNode(DLinkType value){
DLinkNode* New_Node = (DLinkNode*)malloc(sizeof(DLinkNode));
New_Node->data = value;
New_Node->next = NULL;
New_Node->prev = NULL;
return New_Node;
}
//实现打印
void DLinkListPrint(DLinkNode* head,const char* msg){
if(head == NULL){
printf("非法输入\n");
return;
}
printf("[*****%s*****]\n",msg);
DLinkNode* cur = head->next;
for(; cur != head; cur = cur->next){
printf("[%c|%p]\t",cur->data,cur);
}
printf("\n");
return;
}
//实现初始化
void DLinkListInit(DLinkNode** head){
if(head == NULL){
//非法输入
return;
}
*head =DLinkListCreatNode(0);
(*head)->prev = *head;
(*head)->next = *head;
return;
}
//实现尾插
void DLinkListPushBack(DLinkNode* head, DLinkType value){
if(head == NULL){
//非法输入
return;
}
DLinkNode* New_Node = DLinkListCreatNode(value);
New_Node->data = value;
DLinkNode* tail = head->prev;
//此时三个值 tail(原来的末尾) head(头) New_Node(新加入的值,现在的末尾)
//实现两组指针的指向prev和next的指向
New_Node->next = head;
head->prev = New_Node;
New_Node->prev = tail;
tail->next = New_Node;
}
//尾删
void DLinkListPopBack(DLinkNode* head){
if(head == NULL){
//非法输入
return;
}
if(head->next == NULL){
//空链表
return;
}
DLinkNode* tailprev = head->prev->prev;
free(tailprev->next);
tailprev->next = head;
head->prev = tailprev;
}
//头插
void DLinkListPushFront(DLinkNode*head, DLinkType value){
if(head == NULL){
//非法输入
return;
}
DLinkNode* New_Node = DLinkListCreatNode(value);
New_Node->next = head->next;
New_Node->next->prev = New_Node;
head->next = New_Node;
New_Node->prev = head;
}
//头删
void DLinkListPopFront(DLinkNode* head){
if(head == NULL){
//非法输入
return;
}
if(head->next == NULL){
printf("空链表\n");
return;
}
DLinkNode* to_deleted = head->next;
head->next = to_deleted->next;
to_deleted->next->prev = head;
free(to_deleted);
}
//查找
DLinkNode* DLinkListFind(DLinkNode* head,DLinkType to_find){
if(head == NULL){
return;
}
DLinkNode* cur = head->next;;
while(cur != head){
if(cur->data == to_find){
return cur;
}
cur = cur->next;
}
return NULL;
}
//在指定位置之前插入一个元素
void DLinkListInsert(DLinkNode* pos,DLinkType value){
if(pos == NULL){
return;
}
DLinkNode* New_Node = DLinkListCreatNode(value);
DLinkNode* cur = pos->prev;
cur->next = New_Node;
New_Node->prev = cur;
New_Node->next = pos;
pos->prev = New_Node;
}
//在制定元素位置之后插入一个元素
void DLinkListInsertAfter(DLinkNode* pos,DLinkType value){
if(pos == NULL){
return;
}
DLinkNode* New_Node = DLinkListCreatNode(value);
DLinkNode* Next_Node =pos->next;
New_Node->next = Next_Node;
Next_Node->prev = New_Node;
pos->next = New_Node;
New_Node->prev = pos;
}
//////////////////////////////////////////////
//********************************************
//*********Test Code**************************
//////////////////////////////////////////////
//测试尾插
void TestDLinkListPushBack(){
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkListPrint(head,"尾插元素");
}
//测试尾删
void TestDLinkListPopBack(){
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkListPopBack(head);
DLinkListPrint(head,"尾删元素");
}
//测试头插
void TestDLinkListPushFront(){
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushFront(head,'a');
DLinkListPushFront(head,'b');
DLinkListPushFront(head,'c');
DLinkListPushFront(head,'d');
DLinkListPrint(head,"头插元素");
}
//测试头删
void TestDLinkListPopFront(){
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkListPopFront(head);
DLinkListPrint(head,"头删元素");
}
//测试在一个元素之前插入
void TestDLinkListInsert(){
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkNode* pos = DLinkListFind(head,'c');
DLinkListInsert(pos,'x');
DLinkListPrint(head,"在元素之前插入一个元素");
}
//测试在一个元素之后插入
void TestDLinkListInsertAfter(){
DLinkNode* head;
DLinkListInit(&head);
DLinkListPushBack(head,'a');
DLinkListPushBack(head,'b');
DLinkListPushBack(head,'c');
DLinkListPushBack(head,'d');
DLinkNode* pos = DLinkListFind(head,'c');
DLinkListInsertAfter(pos,'x');
DLinkListPrint(head,"在元素之后插入一个元素");
}
int main(){
TestDLinkListPushBack();
TestDLinkListPopBack();
TestDLinkListPushFront();
TestDLinkListPopFront();
TestDLinkListInsert();
TestDLinkListInsertAfter();
return 0;
}
LinkList.h:
#pragma once
typedef char DLinkType;
typedef struct DLinkNode{
DLinkType data;
struct DLinkNode* next; //指向下一个结点
struct DLinkNode* prev; //指向上一个结点
}DLinkNode;
//创建一个新结点
DLinkNode* DLinkListCreatNode(DLinkType value);
//打印
void DLinkListPrint(DLinkNode* head,const char* msg);
//初始化
void DLinkListInit(DLinkNode** head);
//尾插
void DLinkListPushBack(DLinkNode* head, DLinkType value);
//尾删
void DLinkListPopBack(DLinkNode* head);
//头插
void DLinkListPushFront(DLinkNode* head, DLinkType value);
//头删
void DLinkListPopFront(DLinkNode* head);
下一篇: vue路由嵌套+路由导航-学习笔记