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

1.带头节点的单链表。

//结点定义:
typedef int DataType; //定义抽象数据类型
//节点的结构体
typedef struct Node
{ 
    DataType data;   //节点的数据域
    struct Node *next; //节点的指针域
} SLNode;
//初始化ListInitiate(head)
void ListInitiate(SLNode **head)
{
    *head = (SLNode *)malloc(sizeof(SLNode));
    (*head)->next = NULL;
}

这里参数使用了指针的指针,是为了使主函数里的头指针指向这个函数开辟的空间节点,使用指针的指针保存的是头指针的地址,那么对这个地来址里面值的改变,就是对头指针里面值得改变,这里需要使用指针的指针,来进行对实参值的改变。

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

求当前数据元素个数的操作:先定义一个指向头结点的指针*p=head;,通过移动指针的指向,同时size++,达到遍历链表的目的,当指针指向空的时候,链表遍历结束,此时size就是当前数据元素的个数。
在这里插入图片描述

//插入ListInsert(head, i, x)
int ListInsert(SLNode *head, int i, DataType x)
{
    SLNode *p, *q;
    int j;
    p = head;
    j = -1;
    while (p->next != NULL && j < i - 1)
    {
        p = p->next;
        j++;
    }
    if (j != i - 1)
    {
        printf("插入位置参数错!");
        return 0;
    }
    q = (SLNode *)malloc(sizeof(SLNode));
    q->data = x;
    q->next = p->next;
    p->next = q;
    return 1;
}

在这里插入图片描述
说明:①要在带头结点的单链表第i(0 ≤ i ≤ size)个结点前插入一个存放数据元素x的结点,首先要在单链表中寻找到第i-1个结点并由指针p指示,然后动态申请一个结点存储空间并由指针q指示,并把数据元素x的值赋予新结点的数据元素域(即q->data = x),最后修改新结点的指针域指向ai结点(即q->next = p->next),并修改ai-1结点的指针域指向新结点q(即p->next = q)。
②循环条件由两个子条件逻辑与组成,其中子条件p->next != NULL保证指针所指结点存在,子条件j < i - 1保证最终让指针p指向ai-1结点。

//删除ListDelete(head, i, x)
int ListDelete(SLNode *head, int i, DataType *x)
{
    SLNode *p, *s;
    int j;
    p = head;
    j = -1;
    while (p->next != NULL && p->next->next != NULL && j < i - 1)
    {
        p = p->next;
        j++;
    }
    if (j != i - 1)
    {
        printf("插入位置参数错!");
        return 0;
    }
    s = p->next;
    *x = s->data;
    p->next = p->next->next;
    free(s);
    return 1;
}

在这里插入图片描述
说明:要在带头结点的单链表中删除第i(0 ≤ i ≤ size - 1)个结点,首先要在单链表中寻找到第i-1个结点并由指针p指示,然后让指针s指向ai结点(即s = p->next),并把数据元素ai的值赋予x(即*x = s->data),最后把ai结点脱链(即p->next = p->next->next),并动态释放ai结点的存储空间(即free(s))。删除过程上图所示。图中的①对应算法中的删除语句。

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

单链表求数据元素个数操作的时间复杂度为O(n)。
主要优点是不需要预先确定数据元素的最大个数,插入和删除操作不需要移动数据元素;
主要缺点是查找数据元素时需要顺序进行,不能像顺序表那样随机查找任意一个数据元素。另外,每个结点中要有一个指针域,因此空间单元利用率不高。而且单链表操作的算法也较复杂。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值