数据结构算法-双向循环链表的增删改查

774 阅读3分钟

话不多说,双向循环链表,也就是如图所示的一种双向指针的数据结构,从下图中可以看到,双向链表中各节点包含以下 3 部分信息(如下图所示): 指针域 prior:用于指向当前节点的直接前驱节点; 数据域 data:用于存储数据元素。 指针域 next:用于指向当前节点的直接后继节点; 当仅有一个数据的时候,next、prior都是指向本身.

数据结构如下:


typedef  struct Node {
    elemType data;
    struct  Node * prior;
    struct  Node * next;
}Node;

typedef Node * linkList;

首先我们通过initList 创建一个双向循环链表


Status initList(linkList * L ){
    *L = (linkList)malloc(sizeof(Node));
    if ((*L)==NULL)return ERROR;
    (*L)->data = -1;
    (*L)->next = *L;
    (*L)->prior = *L;
    return SUCCESS;
}

creatLinkList 创建一个双向循环链表输入数据 以0 为结束,代码如下


Status creatLinkList(linkList * L )
{
    if (*L == NULL) return  ERROR;
    elemType d;
    linkList headList = (*L);
    linkList lastList = (*L);
    printf("请输入数据为0时表示退出:");
    
    while (1) {
    
        scanf("%d",&d);
        if (d == 0) break;
    
        linkList temp = (linkList)malloc(sizeof(Node));
        temp->data = d;
        temp ->prior = lastList;
        temp ->next  = headList;
        lastList->next = temp;
        headList->prior = temp;
        lastList = temp;
    }
    return SUCCESS;
}

根据index 插入数据e

/// 插入数据
Status insertLinkList(linkList * L ,int index , elemType e )
{
 if ((*L) == NULL || index<1) return ERROR;
    linkList header  = (*L);
    linkList p  = header->next;
    
//     查找到第 index 个
    int j ;
    for (j=1; j<index && p->next != header; j++,p = p->next);
    if (j<index) return ERROR;
    
    linkList  temp = (linkList)malloc(sizeof(Node));
    temp->data = e;
    temp->next = p;
    temp->prior = p ->prior;
    p ->prior->next = temp;
    p ->prior = temp;
    
    return SUCCESS;
}

根据index 删除数据e


/// 删除数据
Status delectLinkList(linkList * L ,int index )
{
    if ((*L) == NULL || index<1) return ERROR;

    linkList header  = (*L);
    linkList p  = header->next;
//     查找到第 index 个
    int j ;
    for (j=1; j<index && p->next != header; j++,p = p->next);
    if (j<index) return ERROR;
    p->prior->next = p ->next;
    p ->next->prior = p->prior;
    free(p);
    
    return SUCCESS;
}

根据index 修改数据e


/// 修改数据
Status replaceLinkList(linkList * L ,int index ,elemType  e)
{
    if ((*L) == NULL || index<1) return ERROR;

    linkList header  = (*L);
    linkList p  = header->next;
//     查找到第 index 个
    int j ;
    for (j=1; j<index && p->next != header; j++,p = p->next);
    if (j<index) return ERROR;
    p->data = e;
    return SUCCESS;
}


查看链表-正序


///顺序查看
Status checkLinkList(linkList * L )
{
    linkList temp  = (*L) ->next;
    
    while (temp != *L) {
        printf("%d  " ,temp->data);
        temp = temp->next;
    }
     printf("\n");
    return SUCCESS;
}

查看链表-倒序


///倒序查看
Status checkLinkList2(linkList * L )
{
    linkList temp  = (*L) ->prior;
    
    while (temp != *L) {
        printf("%d  " ,temp->data);
        temp = temp->prior;
    }
    printf("\n");
    return SUCCESS;
}

main函数调用如下

#define ERROR 0
#define TRUE 1
#define FALSE 0
#define SUCCESS 1
typedef int Status;
typedef int elemType;
int main(int argc, const char * argv[]) {
    
    linkList L;
//    初始化
    initList(&L);
//    创建
    creatLinkList(&L);
//    正序打印
    checkLinkList(&L);
//    倒叙打印
    checkLinkList2(&L);
//    插入数据
    insertLinkList(&L, 3, 20);
//    打印
    checkLinkList(&L);
    checkLinkList2(&L);
//    删除
    delectLinkList(&L, 3);
//    打印
    checkLinkList(&L);
    checkLinkList2(&L);
    
    return 0;
}

总结:通过以上代码我们可以看出,双向循环链表还是就是一种双向的可以方便查找上一个节点的数据结构,在增删中只要记住,链表断开时候不要丢失链接就可以了,双向链表相比与双向循环链表,也就是首节点的priot 为NULL,尾节点的next也等于NULL,其他的保持一致.