数据结构——线性表链式存储结构4(C语言)

4.双向链表
双向链表是每个结点除后继指针域外还有一个前驱指针域,它有带头结点和不带头结点,循环和非循环结构,双向链表是解决查找前驱结点问题的有效途径。
结点结构如图示:
在这里插入图片描述
下图是带头结点的循环双向链表的结构,可见,其前驱指针和后继指针各自构成自己的循环单链表。
设指针p指向第i个数据元素结点,则p->next指向第i+1个数据元素结点,p->next->prior仍指向第i个数据元素结点,即p->next->prior=p;同样p->prior->next=p。
在这里插入图片描述
循环双向链表的插入过程如图示:在这里插入图片描述
删除过程如图示:
在这里插入图片描述

typedef int DataType; //定义抽象数据类型
//节点的结构体
typedef struct Node
{
    DataType data;      //节点的数据域
    struct Node *next;  //节点的尾指针域
    struct Node *prior; //
} SLNode;

//初始化ListInitiate(head)
void ListInitiate(SLNode **head)
{
    *head = (SLNode *)malloc(sizeof(SLNode));
    (*head)->prior = *head; //构成前驱指针循环链表
    (*head)->next = *head;  //构成后继指针循环链表
}

//求当前数据元素个数ListLength(head)
int ListLength(SLNode *head)
{
    SLNode *p = head;
    int size = 0;
    while (p->next != head)
    {
        p = p->next;
        size++;
    }
    return size;
}

//插入数据元素
int ListInsert(SLNode *head, int i, DataType x)
//在带头结点的双向循环链表head的第i个结点前,插入一个存放
//数据元素x的结点,插入成功返回1,失败返回0
{
    SLNode *p, *s;
    int j;
    p = head->next;
    j = 0;
    while (p != head && j < i)
    {
        p = p->next;
        j++;
    }
    if (j != i)
    {
        printf("参数i错误!");
        return 0;
    }
    s = (SLNode *)malloc(sizeof(SLNode));
    s->data = x;
    s->prior = p->prior; //新结点指向前一个结点(中——>前)
    p->prior->next = s;  //新结点结点指向前一个结点(前->中)
    s->next = p;         //新节点指向后结点    (中->后)
    p->prior = s;        //后结点指向新节点    (后->中)
    return 1;
}

//取数据元素ListGet(head, i, x)
int ListGet(SLNode *head, int i, DataType *x)
{
    SLNode *p;
    int j;
    p = head;
    j = -1;
    while (p->next != head && j < i)
    {
        p = p->next;
        j++;
    }
    if (j != i)
    {
        printf("取元素位置参数错!");
        return 0;
    }
    *x = p->data;
    return 1;
}


//删除ListDelete(head, i, x)
int ListDelete(SLNode *head, int i, DataType *x)
{
    SLNode *p;
    int j;
    p = head->next;
    j = 0;
    while (p->next != head && p->next ->next != head&& j < i )
    {
        p = p->next;
        j++;
    }
    if (j != i)
    {
        printf("删除数据元素为值参数出错!");
        return 0;
    }
    *x = p->data;
    p->prior->next = p->next;
    p->next -> prior = p->prior;
    free(p);
    return 1;
}

//撤销内存空间DestroyList(SLNode **head)
void DestoryList(SLNode **head)
{
    SLNode *p,*q;
    int i,n=ListLength(*head);
    p=*head;
    for(i=0;i<=n;i++)
    {
        q=p;
        p=p->next;
        free(p);
    }
    *head=NULL;
}

5.静态链表
在数组中增加一个(或两个)指针域用来存放下一个(或上一个)数据元素在数组中的下标,从而构成用数组构造的单链表。因为数组内存空间的申请方式是静态的,所以称为静态链表,增加的指针称做仿真指针。
结构如下:
在这里插入图片描述
在这里插入图片描述

#define TRUE 1
#define FALSE 0
#define MAX_LEN 100

typedef int Status;
typedef int ElemType;

typedef struct _tag_staticlist
{
    ElemType data;
    int cur;
} StaticList, List[MAX_LEN];

/* Init StaticList */
Status InitList(StaticList *list)
{
    int i = 0;

    for (i = 0; i < MAX_LEN - 1; i++)
    {
        list[i].cur = i + 1;
        list[i].data = 0; //此处初始化为0 是为了方便观看 实际中ElemType不一定是int型
    }

    list[MAX_LEN - 1].cur = 0;
    list[MAX_LEN - 1].data = 0;

    return TRUE;
}

/* Display StaticList */
void DisplayList(StaticList *list)
{
    int i = 0;

    for (i = 0; i < MAX_LEN; i++)
    {
        printf("%d.cur = %d, %d.data = %d\n", i, list[i].cur, i, list[i].data);
    }

    return;
}

/* Malloc StaticList, Get Free Space */
int Malloc_SL(StaticList *list)
{
    int ret = 0;

    ret = list[0].cur;

    list[0].cur = list[ret].cur; // 指向下一个节点的cur

    return ret;
}

/* Free StaticList, Free Space */
Status Free_SL(StaticList *list, int j)
{
    list[j].cur = list[0].cur; // 保存备用链表第一个节点下一个节点cur

    list[0].cur = j; // j成为备用链表的首节点下标

    return TRUE;
}

/* Insert StaticList */
Status InsertList(StaticList *list, int pos, ElemType data)
{
    int i = 0;
    int j = 0;
    int k = MAX_LEN - 1;

    if (pos < 1 || NULL == list || pos >= MAX_LEN - 1)
        return FALSE;

    j = Malloc_SL(list); // Malloc cur
    list[j].data = data; // Insert data
    for (i = 1; i < pos; i++)
    {
        k = list[k].cur;
    }

    list[j].cur = list[k].cur;
    list[k].cur = j;

    return TRUE;
}

Status InsertList(StaticList *list, int pos, ElemType *ret)
{
    int i = 0;
    int j = 0;
    int k = MAX_LEN - 1;

    if (pos < 1 || NULL == list || pos >= MAX_LEN - 1)
        return FALSE;

    for (i = 1; i < pos; i++)
    {
        k = list[k].cur;
    }

    j = list[k].cur;

    *ret = list[j].data;

    Free_SL(list, j);

    return TRUE;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值