目录
[一. 逻辑结构图解](#一. 逻辑结构图解)
[1. 节点中存储的值](#1. 节点中存储的值)
[二. 各种功能实现](#二. 各种功能实现)
[1. 创建节点函数](#1. 创建节点函数)
[2. 初始化哨兵位](#2. 初始化哨兵位)
[3. 尾插](#3. 尾插)
[4. 头插](#4. 头插)
[5. 尾删](#5. 尾删)
[6. 头删](#6. 头删)
[7. 打印链表值](#7. 打印链表值)
[8. 查找数据,返回节点地址](#8. 查找数据,返回节点地址)
[9. 指定地址后插入节点](#9. 指定地址后插入节点)
[10. 删除指定地址节点](#10. 删除指定地址节点)
[11. 销毁链表](#11. 销毁链表)
[三. 完整代码](#三. 完整代码)
[1. list.h](#1. list.h)
[2. list.c](#2. list.c)
[3. 测试](#3. 测试)
由于上一篇已经对链表的基本概念讲解完毕,这里就不过多赘述了
一. 逻辑结构图解
1. 节点中存储的值
qrev是上一个节点的地址
data是节点中存储的数据
next是下一个节点的位置
2.逻辑实现
第一个节点为哨兵位不存储数据
二. 各种功能实现
1. 创建节点函数
cpp
ListNode* BuyListNode(DataType x)
{
ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
if (newnode == NULL)
{
exit(-1);
}
newnode->data = x;
newnode->next = newnode->prev = newnode;
return newnode;
}
2. 初始化哨兵位
由于需要改变哨兵位本身,所以用二级指针
之后就不用改变哨兵位了所以不用用二级指针
cpp
void ListNodeInit(ListNode** pphead)
{
*pphead = BuyListNode(0);
}
3. 尾插
cpp
void ListNodePushBack(ListNode* phead, DataType x)
{
ListNode* tail = phead->prev;
assert(phead);
ListNode* newnode = BuyListNode(x);
newnode->prev = phead->prev;
newnode->next = phead;
tail->next = newnode;//之前的尾指向现在的尾
phead->prev = newnode;//头的上一个改为现在的尾
}
4. 头插
cpp
void ListNodePushFront(ListNode* head,DataType x)
{
assert(head);
ListNode* first = head->next;
ListNode* newnode = BuyListNode(x);
newnode->next = head->next;
newnode->prev = head;
first->prev = newnode;
head->next = newnode;
}
5. 尾删
cpp
void ListNodePopBack(ListNode* head)
{
assert(head);
ListNode* tail=head->prev;
ListNode* newtail = tail->prev;
head->prev = newtail;
newtail->next = head;
free(tail);
tail = NULL;
}
6. 头删
cpp
void ListNodePopFront(ListNode* head)
{
assert(head);
ListNode* first=head->next;
ListNode* newfirst = first->next;
head->next = newfirst;
newfirst->prev = head;
free(first);
first = NULL;
}
7. 打印链表值
cpp
void ListNodePrint(ListNode* phead)
{
assert(phead);
ListNode* tmp = phead->next;
while (tmp!= phead)
{
printf("%d ", tmp->data);
tmp = tmp->next;
}
}
8. 查找数据,返回节点地址
cpp
ListNode* ListNodeFind(ListNode* head,DataType x)
{
assert(head);
ListNode* tmp = head->next;
while (tmp!=head)
{
if (tmp->data == x)
return tmp;
tmp = tmp->next;
}
return NULL;
}
9. 指定地址后插入节点
cpp
void ListNodeInsert(ListNode* pos, DataType x)
{
assert(pos);
ListNode* newnext = pos->next;
ListNode* newnode = BuyListNode(x);
newnode->prev = pos;
newnode->next = newnext;
pos->next = newnode;
newnext->prev = newnode;
}
10. 删除指定地址节点
cpp
void ListNodeErase(ListNode* pos)
{
assert(pos);
ListNode* posprev = pos->prev, * posnext = pos->next;
posprev->next = posnext;
posnext->prev = posprev;
free(pos);
pos = NULL;
}
11. 销毁链表
cpp
void ListNodeDestroy(ListNode* head)
{
assert(head);
ListNode* cur = head->next;
while (cur != head)
{
ListNode* next = cur->next;
free(cur);
cur = next;
}
}
三. 完整代码
1. list.h
cpp
#define _CRT_SECURE_NO_WARNINGS h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int DataType;
typedef struct ListNode
{
DataType data;
struct SList* next;
struct SList* prev;
}ListNode;
//初始化
void ListNodeInit(ListNode** pphead);
//尾插
void ListNodePushBack(ListNode* head, DataType x);
//打印链表
void ListNodePrint(ListNode* phead);
//头插
void ListNodePushFront(ListNode* head, DataType x);
//尾删
void ListNodePopBack(ListNode* head);
//头删
void ListNodePopFront(ListNode* head);
//查找数据
ListNode* ListNodeFind(ListNode* head, DataType x);
//指定位置后插入
void ListNodeInsert(ListNode* pos, DataType x);
//指定位置删除
void ListNodeErase(ListNode* pos);
//销毁链表
void ListNodeDestroy(ListNode* head);
2. list.c
cpp
#define _CRT_SECURE_NO_WARNINGS h
#include"list.h"
ListNode* BuyListNode(DataType x)
{
ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
if (newnode == NULL)
{
exit(-1);
}
newnode->data = x;
newnode->next = newnode->prev = newnode;
return newnode;
}
void ListNodeInit(ListNode** pphead)
{
*pphead = BuyListNode(0);
}
void ListNodePushBack(ListNode* phead, DataType x)
{
ListNode* tail = phead->prev;
assert(phead);
ListNode* newnode = BuyListNode(x);
newnode->prev = phead->prev;
newnode->next = phead;
tail->next = newnode;//之前的尾指向现在的尾
phead->prev = newnode;//头的上一个改为现在的尾
}
void ListNodePrint(ListNode* phead)
{
assert(phead);
ListNode* tmp = phead->next;
while (tmp!= phead)
{
printf("%d ", tmp->data);
tmp = tmp->next;
}
}
void ListNodePushFront(ListNode* head,DataType x)
{
assert(head);
ListNode* first = head->next;
ListNode* newnode = BuyListNode(x);
newnode->next = head->next;
newnode->prev = head;
first->prev = newnode;
head->next = newnode;
}
void ListNodePopBack(ListNode* head)
{
assert(head);
ListNode* tail=head->prev;
ListNode* newtail = tail->prev;
head->prev = newtail;
newtail->next = head;
free(tail);
tail = NULL;
}
void ListNodePopFront(ListNode* head)
{
assert(head);
ListNode* first=head->next;
ListNode* newfirst = first->next;
head->next = newfirst;
newfirst->prev = head;
free(first);
first = NULL;
}
ListNode* ListNodeFind(ListNode* head,DataType x)
{
assert(head);
ListNode* tmp = head->next;
while (tmp!=head)
{
if (tmp->data == x)
return tmp;
tmp = tmp->next;
}
return NULL;
}
void ListNodeInsert(ListNode* pos, DataType x)
{
assert(pos);
ListNode* newnext = pos->next;
ListNode* newnode = BuyListNode(x);
newnode->prev = pos;
newnode->next = newnext;
pos->next = newnode;
newnext->prev = newnode;
}
void ListNodeErase(ListNode* pos)
{
assert(pos);
ListNode* posprev = pos->prev, * posnext = pos->next;
posprev->next = posnext;
posnext->prev = posprev;
free(pos);
pos = NULL;
}
void ListNodeDestroy(ListNode* head)
{
assert(head);
ListNode* cur = head->next;
while (cur != head)
{
ListNode* next = cur->next;
free(cur);
cur = next;
}
}
3. 测试
cpp
#define _CRT_SECURE_NO_WARNINGS h
#include"list.h"
void test()
{
ListNode* head=NULL;
ListNodeInit(&head);
ListNodePushBack(head, 2);
ListNodePushBack(head, 45);
ListNodePushBack(head, 33);
ListNodePushFront(head, 22);
ListNodePushFront(head, 66);
ListNode* find=ListNodeFind(head,33);
ListNodeInsert(find, 666);
ListNodePrint(head);
printf("\n");
//ListNodePopBack(head);
ListNodeErase(find);
ListNodePopFront(head);
ListNodePrint(head);
}
int main()
{
test();
}
感谢大家观看,希望可以帮到您
(づ ̄3 ̄)づ╭❤~