双向循坏链表的展现

首先在看这篇文章之前,建议大家先把单项列表的内容融合掌握,其实双向循坏列表虽然从结构上来讲更为复杂,但是从实现的角度来讲其实比单项列表更为简单。

从原理上来讲无非就是在单链表的基础上在每一个节点处多加入了一处地址让前后列表都能相互访问到,(第一个结点放最了最后一个节点的地址,最后一个节点放了第一个节点的地址。

废话不多说,直接上结构体的定义:

typedef int LTDataType;
typedef struct ListNode
{
    LTDataType data;
    struct ListNode* next;  //存放下一个节点的地址
    struct ListNode* prev;  //存放上一个节点的地址
}LTNode;

1.已经是我们熟悉的第一步操作:初始化
LTNode*ListInit()  //单纯的创建一块空间不接收任何的值
{
    LTNode* phead = (LTNode*)malloc(sizeof(LTNode));
    if(phead == NULL)
    {
        printf("开创失败\n");
        return;
    }
    phead->next = phead; // 将自己的首尾插入自己的地址
    phead->prev = phead;
    return phead;
}
2.最为基础的功能实现:打印
void ListPrint(LTNode* phead)
{
    assert(phead);
    LTNode* cur = phead->next; //其实就是单纯的留了一个没有存储任何数值的哨兵位
    while( cur != NULL )
    {
       printf("%d" , cur->data);
       cur = cur->next;
    }
    printf("\n");
}
3.创建一个空间并且可插入的值为x
LTnode* BuyListNode(LTDataType x)
{
     LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
     if(newnode == NULL)
    {
        printf("开创失败\n");
        return;
    }
    newnode->data = x;
    newnode->next = NULL;
    newnode->prv = NULL;
    return newnode;
}
4.后插
void ListPushBack (LTNode* phead , LTDataType x)  
{
    assert(phead);
    LTNode* tail = phead->prev;   //实际就是通过首地址里面的prev找到了tail这个目前列表的尾,可以结合初始化那看看,初始化的时候其实是把那第一块结构体给留了下来(没插入任何数值的那种)
    LTNode* newnode = BuyListNode(x); 
    tail->next = newnode;
    newnode->next = phead;
    newnode->prev = tail;
    phead->prev = newnode;
}
5.后删
void ListPopBack (LTNode* phead)
{
    assert(phead);
    assert(phead->next != phead); //保证我已经插入了至少一个数据了
    LTNode* tail = phead->prev;
    LTNode* tailPrev = tail->prev;
    free(tail);
    tailPrev->next = phead;
    phead->prev = tailPrev;
    tail = NULL;
}
6.前插
void ListPushFront (LTNode* phead , LTDataType x)
{
    assert(phead);
    LTNode*newnode = BuyListNode(x);
    LTNode*next = phead->next;
    phead->next = newnode;
    newnode->next = next;
    newnode->prev = phead;
    next->prev = newnode;
}
7.前删
void ListPopFront (LTNode* phead)
{
     assert(phead);
     assert(phead->next != phead); 
     LTNode* next = phead->next;
     LTNode* nextNext = next->next
     free(next);
     next = NULL;
     prev->next =nextNext;
     nextNext->prev = phead;
}
8.查找存储数值的位置
LTNode* ListFind(LTNode* phead, LTDataType x)
{
    assert(phead);
    LTNode* cur = phead->next;
    while(cur!=phead)
    {
        if(cur->data == x)
        {
            return cur;
        }
        cur = cur->next;
    }
    printf("\n");
}
9.在pos位置之前插入节点
void ListInsert(LTNode*pos , LTDataType x)
{
    assert(pos);
    LTNode* newnode = BuyListNode(x);
    LTNode* posPrev = pos->prev;
    pos->prev = newnode;
    newnode->next = pos;
    newnode->prev = posPrev;
    posPrev->next = newnode;
}
    
    
10.在pos位置前面删除节点
void ListErase(LTNode*pos)
{
    LTNode* posPrev = pos->prev;
    LTNode* prevPrev = posPrev->prev;
    free(posPrev);
    posPrev = NULL;
    pos->prev = prevPrev;
    prevPrev->next = pos;
}

你可能感兴趣的:(链表,数据结构)