带头双向循环链表的增删查改

typedef int LTDateType;

typedef struct ListNode//双向循环链表结点
{
    LTDateType val;
    struct ListNode* next;
    struct ListNode* prev;
}LTNode;

//创建一个哨兵位的头结点,并返回地址
LTNode* ListInit()
{
    LTNode* phead = (LTNode*)malloc(sizeof(LTNode));
    phead->next = phead;//尾指向头
    phead->prev = phead;//头指向尾

    return phead;
}
//打印
void ListPrint(LTNode* phead)
{
    assert(phead);
    //phead为哨兵位的头结点,打印从phead->next指向的结点开始
    //尾节点的next指向的是哨兵位的头结点,遇到头结点停止打印
    LTNode* cur = phead->next;
    while (cur != phead)
    {
        printf("%d ", cur->val);
        cur = cur->next;
    }
    printf("\n");
}

//给插入元素x创建开辟一个结点
LTNode* BuyListNode(LTDateType x)
{
    LTNode* newNode = (LTNode*)malloc(sizeof(LTNode));
    newNode->val = x;
    newNode->prev = NULL;
    newNode->next = NULL;

    return newNode;
}
//尾插
void ListPushBack(LTNode* phead, LTDateType x)
{
    //结点不为NULL
    assert(phead);

    //phead指向尾部的结点地址赋给tail
    LTNode* tail = phead->prev;

    //给插入元素x创建开辟一个结点
    LTNode* newNode = BuyListNode(x);

    //结点尾插
    tail->next = newNode;
    newNode->prev = tail;

    //头尾相连
    phead->prev = newNode;
    newNode->next = phead;
    
    //引用ListInsert尾插
    //ListInsert(phead->prev, x);
}
//尾删
void ListPopBack(LTNode* phead)
{
    //指针不为空
    assert(phead);
    //哨兵位头结点指向的不是自己,保证链表内部有有效结点
    assert(phead->next != phead);
    //找到尾结点
    LTNode* tail = phead->prev;
    //修改尾结点的前一个结点,使之首尾循环
    LTNode* tailPrev = tail->prev;
    tailPrev->next = phead;
    phead->prev = tailPrev;
    //释放删除的尾结点空间内存
    free(tail);

    //引用ListErase尾删
    ListErase(phead->prev);
}
//头插
void ListPushfront(LTNode* phead, LTDateType x)
{
    //指针不为空
    assert(phead);

    //给插入元素x创建开辟一个结点
    LTNode* newNode = BuyListNode(x);

    //创建一个指针指向第一个有效头结点
    LTNode* next = phead->next;

    //与哨兵位链接
    phead->next = newNode;
    newNode->prev = phead;

    //与头结点链接,称为新头结点
    newNode->next = next;
    next->prev = newNode;

    //引用ListInsert头插
    //ListInsert(phead->next, x);
}
//头删
void ListPopFront(LTNode* phead)
{
    //指针不为空
    assert(phead);

    //哨兵位头结点指向的不是自己,保证链表内部有有效结点
    assert(phead->next != phead);

    //找到要删除的头部结点
    LTNode* next = phead->next;

    //找到要删除的头部结点的下一个结点
    LTNode* nextNext = next->next;

    //哨兵位与nextNext链接
    phead->next = nextNext;
    nextNext->prev = phead;
    //释放删除的头结点的空间
    free(next);

    //引用ListErase头删
    //ListErase(phead->next);
}
//查找
LTNode* ListFind(LTNode* phead, LTDateType x)
{
    assert(phead);
    //phead为哨兵位的头结点,查找从phead->next指向的结点开始
    //尾节点的next指向的是哨兵位的头结点,遇到头结点停止查找
    LTNode* cur = phead->next;
    while (cur != phead)
    {
        if (cur->val == x)
        {
            return cur;//返回x所在的位置pos
        }
        cur = cur->next;
    }
    return NULL;
}
//指定位置前插入
void ListInsert(LTNode* pos, LTDateType x)
{
    assert(pos);
    //找到pos结点前一个结点
    LTNode* posPrev = pos->prev;
    //创建新结点
    LTNode* newNode = BuyListNode(x);
    //建立链接
    posPrev->next = newNode;
    newNode->prev = posPrev;

    newNode->next = pos;
    pos->prev = newNode;
}
//指定位置删除
void ListErase(LTNode* pos)
{
    assert(pos);
    //找到pos结点前一个结点
    LTNode* posPrev = pos->prev;
    //找到pos结点后一个结点
    LTNode* posNext = pos->next;
    //链接
    posPrev->next = posNext;
    posNext->prev = posPrev;
    //释放pos结点空间
    free(pos);
    pos = NULL;
}
//销毁
void ListDestroy(LTNode* phead)
{
    assert(phead);
    //创建当前指针指向第一个有效结点
    LTNode* cur = phead->next;
    //开始销毁,直到cur指向哨兵位phead结点
    while (cur != phead)
    {
        //记录cur结点的下一个结点
        LTNode* next = cur->next;
        //销毁
        free(cur);
        //cur迭代往后走
        cur = next;
    }
    //只剩下最后的哨兵位,函数外部置空,即plist = NULL
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值