4-双向链表

单向链表的缺点
单向链表相对数组来说已经有很多优点了,但是,它还有一个最大的弊端,那就是我们可以轻松的到达下一个节点, 但是回到前一个节点是很难的. 但是, 在实际开发中, 经常会遇到需要回到上一个节点的情况,这种特性在进行数据操作时,会大大浪费时间,鉴于此,出现了双向链表的概念。

双向链表就是具备两个方向的指向,无非就是每个结点成了两个指针。
每个数据节点有一个数据域两个个指针域 不光从前向后检索 还能从后向前

每次在插入或删除某个节点时, 需要处理四个节点的引用, 而不是两个. 也就是实现起来要困难一些,并且相当于单向链表, 必然占用内存空间更大一些.
1.创建双链表
在这里插入图片描述
有两个指针域分别指向前一个结点和后一个结点,还有一部分用来保存结点数据,初始化结点时需要将两个指针都指向空

eg:

Node* node = (Node*)malloc(sizeof(Node));
node->prev = NULL;
node->next = NULL;

2.增加结点

增加结点时,需要将最后一个结点的next指针指向新结点,然后将新结点的prev指向最后一个结点
在这里插入图片描述
3.删除结点
删除结点时需要将待删除结点的前一个结点的next指向待删除结点的后一个结点,然后,把后者的prev指针指向前者:
在这里插入图片描述
4.插入结点
插入结点就是将新结点的前一个结点的next指针指向指向新结点,然后把新结点的next指针指向前一个结点原来后面的那个结点,然后把后面的结点的prev指针指向新结点,把新结点的Prev指针指向前一个结点。
在这里插入图片描述
头文件:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int LTDataType;
#define N 10
typedef struct ListNode
{
    struct ListNode* _next;
    struct ListNode* _prev;
    LTDataType _data;
}ListNode;
typedef struct List
{
    struct ListNode* _head;
    struct ListNode* _tail;
    int count;
}List;
void ListInit(List* lt);//初始化
void ListDestory(List* lt);//销毁
void ListPushBack(List* lt, LTDataType x);//在最后插入
void ListPushFront(List* lt, LTDataType x);//在前面插入
void ListPopBack(List* lt);//从最后出一个
void ListPopFront(List* lt);//从最前面出一个
ListNode* ListFind(List* lt, LTDataType x);//查找一个节点
void ListInsert(ListNode* pos, LTDataType x);//插入一个节点
void ListErase(ListNode* pos);//清空列表
int ListSize(List* lt);//返回大小
int ListEmpty(List* lt);//判空
void ListPrint(List* lt);//打印链表
void testLT();

实现:

#include "双向链表.h"
void ListInit(List* lt)//初始化
{
    assert(lt);
    lt->_head = (ListNode*)malloc(sizeof(ListNode)* N);
    lt->_tail = lt->_head;
    lt->count = 0;
}
void ListDestory(List* lt)//销毁
{
    if (lt->count == 0)
    {
        return;
    }
    ListNode* p;
    for (int i = 0; i < lt->count; i++)
    {
        p = lt->_head->_next;
        free(lt->_head);
        lt->_head = p;
    }
    free(lt->_head);
    lt->count = 0;
}
void ListPushBack(List* lt, LTDataType x)//在最后插入
{
    assert(lt);
    ListNode* ptmp = (ListNode*)malloc(sizeof(ListNode));
    ptmp->_data = x;
    
    lt->_tail->_next = ptmp;//把尾巴的后连上这个
    ptmp->_prev = lt->_tail;//把后面的前面连上尾巴
    lt->_tail = ptmp;//吧尾巴变成当前插入的最后一个
    lt->count++;
}
void ListPushFront(List* lt, LTDataType x)//在前面插入
{
    assert(lt);
    if (lt->_tail == lt->_head)
    {
        ListPushBack(lt, x);
        return;
    }
    ListNode* ptmp = (ListNode*)malloc(sizeof(ListNode));
    ptmp->_data = x;
    ptmp->_next = lt->_head->_next;
    lt->_head->_next->_prev = ptmp;
    lt->_head->_next = ptmp;
    ptmp->_prev = lt->_head;
    lt->count++;
}
void ListPopBack(List* lt)//从最后出一个
{
    assert(lt);
    ListNode* p;
    p = lt->_tail;
    lt->_tail = p->_prev;
    free(p);
    lt->count--;
}
void ListPopFront(List* lt)//从最前面出一个
{
    assert(lt);
    ListNode* p;
    p = lt->_head->_next;
    if (1 == lt->count)//最后一个
    {
        ListPopBack(lt);
        return;
    }
    lt->_head->_next = p->_next;
    p->_next->_prev = lt->_head;
    free(p);
    lt->count--;
}
//
//ListNode* BuyListNode(LTDataType x);//
ListNode* ListFind(List* lt, LTDataType x)//查找一个节点
{
    assert(lt);
    ListNode* p;
    p = lt->_head->_next;
    for (int i = 0; i < lt->count; i++)
    {
        if (x == p->_data)
        {
            return p;
        }
        p = p->_next;
    }
    return NULL;
}
//void ListInsert(ListNode* pos, LTDataType x);//插入一个节点
void ListErase(ListNode* pos)//删除某个点
{
    assert(pos);
    pos->_next->_prev = pos->_prev;
    pos->_prev->_next = pos->_next;
    free(pos);
}
int ListSize(List* lt)//返回大小
{
    return lt->count;
}
int ListEmpty(List* lt)//判空
{
    return lt->_tail == lt->_head;
}
void ListPrint(List* lt)//打印链表
{
    assert(lt);
    ListNode* p;
    p = lt->_head->_next;
    for (int i = 0; i < lt->count; i++)
    {
        printf("%d  ", p->_data);
        p = p->_next;
    }
    printf("\n");
}
void testLT(){
    List lt;
    ListInit(&lt);
    ListPushFront(&lt, 5);
    ListPushFront(&lt, 3);
    ListPushBack(&lt, 2);
    ListPushBack(&lt, 8);
    //ListDestory(&lt);
    ListPrint(&lt);
    //ListPopBack(&lt);
    //ListPrint(&lt);
    //ListPopFront(&lt);
    //ListPrint(&lt);
    //ListPopFront(&lt);
    //ListPrint(&lt);
    //ListPopFront(&lt);
    //ListPrint(&lt);
    ListDestory(&lt);
    ListPrint(&lt);
    if (ListFind(&lt, 6))
    {
        printf("%d", ListFind(&lt, 6)->_data);
    }
}
发布了82 篇原创文章 · 获赞 7 · 访问量 4200

猜你喜欢

转载自blog.csdn.net/sunshine612/article/details/104701300
今日推荐