数据结构 03 - 双向循环链表

  双向循环链表在单向循环链表的基础上,结点的结构体内多一个成员,即指向上一个结点的地址的指针域。这就使得双向循环链表在插入、删除等操作中,可以根据插入、删除的位置,判断和结点的距离,从而选择采用从头遍历还是从尾遍历,相较于单向循环链表对于大量数据的处理能够提高效率,但是选择了牺牲一部分空间来存储指向上一个结点的地址。
  下面的dlinklist.c含双向循环链表的相关操作函数,main.c用于测试该链表。
运行结果:
在这里插入图片描述

/*
dlinklist.h
*/
#include <stdio.h>
#include <stdlib.h>

#ifndef __DLINKLIST__
#define __DLINKLIST__

typedef int data_t;

typedef struct dlinklist{
    data_t data;
    struct dlinklist *prior;
    struct dlinklist *next;
}DLinkList,Node;

//创建结点
DLinkList *Create_DLinklist();

//头插法
void DLinklist_Insert_Head(DLinkList *head,data_t data);

//计算表长
int DLinklist_Len(DLinkList *head);

//按位置删除 定位到位置 调用Delete()
void DLinklist_Delete_Pos(DLinkList *head,int pos);

//输入待删除结点地址进行删除
void Delete(DLinkList *p);

//打印
void Show_DLinklist(DLinkList *head);

#endif
/*
dlinklist.c
*/
#include "dlinklist.h"

//创建结点
DLinkList *Create_DLinklist()
{
    DLinkList *head = (DLinkList *)malloc(sizeof(DLinkList));
    if(head == NULL){
        printf("malloc failed!\n");
        return NULL;
    }
    
    head->data = -1;
    head->prior = head;
    head->next = head;

    return head;
}

//头插法
void DLinklist_Insert_Head(DLinkList *head,data_t data)
{
    Node *new = (Node *)malloc(sizeof(Node));
    if(new == NULL){
        printf("Node malloc failed!\n");
        return;
    }

    new->data = data;
    //先完成新结点后的结点 的连接,再进行和头结点的连接
    head->next->prior = new;
    new->next = head->next;

    head->next = new;//该语句需在前两条之后,执行该语句会改变head->next的指向
    new->prior = head;

}

//计算表长
int DLinklist_Len(DLinkList *head)
{
    Node *p = head;
    int len = 0;
    while(p->next != head){
        len++;
        p = p->next;
    }
    
    return len;
}

//按位置删除 头结点后一个结点pos为1
void DLinklist_Delete_Pos(DLinkList *head,int pos)
{
    //判断插入位置是否合理

    Node *p = head;
    int len = DLinklist_Len(head);
    if(len-pos >= pos){//插入位置靠近头 从头遍历
        while(pos--){//遍历到要删除的位置
            p = p->next;
        }
        Delete(p);

    }else{//插入位置靠近尾 从尾遍历
        int i = len-pos+1;
        while(i--){
            p = p->prior;
        }
        Delete(p);
    }
}

//删除结点 输入待删除结点的地址
void Delete(DLinkList *p){
    p->prior->next = p->next;
    p->next->prior = p->prior;
    free(p);
}

//打印
void Show_DLinklist(DLinkList *head)
{
    Node *p = head;
    while(p->next != head){
        p = p->next;
        printf("%d ",p->data);
    }
    puts("");
    
}
/*
main.c
*/
#include "dlinklist.h"

int main()
{
    DLinkList *dlink = Create_DLinklist();
    int n = 10;
    while(n--){//初始化一条链表
        DLinklist_Insert_Head(dlink,n);
    }
    Show_DLinklist(dlink);
    printf("Initial len = %d\n",DLinklist_Len(dlink));

    DLinklist_Delete_Pos(dlink,1);
    printf("\nAfter delete first one len = %d\n",DLinklist_Len(dlink));
    Show_DLinklist(dlink);

    DLinklist_Delete_Pos(dlink,9);
    printf("\nAfter delete last one len = %d\n",DLinklist_Len(dlink));
    Show_DLinklist(dlink);

    return 0;
}
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值