线性表的链式存储

单链表

//线性表的单链存储结构
typedef int EleType;
typedef struct Node
{
    EleType data;
    struct Node *next;
}Node;
//定义LinkList
typedef struct Node *LinkList;

//单链表的读取
//获取链表第i个元素的算法思路:声明一个指针p指向链表的第一个结点,初始化j从1开始;当j<i时,遍历链表,让p的指针向后移动,不断的指向下一个结点,j累加1;若到链表末尾p为空,则说明第i个结点不存在;否则查找成功,返回结点p的数据。

//初始条件:1<=i<=ListLength
Status GetNodeElem(LinkList L, int i, EleType *e)
{
    int j;
    LinkList p;
    p = L->next;
    j = 1;
    while (p && j < i)
    {
        p = p->next;
        j++;
    }
    if (!p || j > i)
        return ERROR;
    *e = p->data;
    return OK;
}

//单链表的插入
//单链表第i个元素插入结点算法思想:声明一个指针p指向链表头结点,初始化j从1开始;当j<i,遍历链表,让j不断向后移动,j+1;若到链表末尾p为空,则说明第i个结点不存在;否则查找成功,在系统中生成一个空结点s;将数据元素e赋值给s->data;单链表的插入标准语句s->next=p->next,p->next=s;返回成功。
#include<stdio.h>
#include<malloc.h>
Status InsToLink(LinkList *L, int i, EleType e)
{
    LinkList p,s;
    int j;
    p = *L;
    j = 1;
    while (p && j<i)
    {
        p = p->next;
        j++;
    }
    if (!p || j>i)
        return ERROR;
    //生成新结点
    s = (LinkList)malloc(sizeof(Node));
    s->data = e;
    s->next = p->next;
    p->next = s->next;
    return OK;

}

//单链表的删除
//单链表第i个元素删除的算法思路:声明p指向表头指针,初始化j从1开始;当j<i,遍历链表,让p向后移动,不断的指向下一个指针,j++;若到末尾p为空,则说明第i个结点不存在;否则查找成功,将欲删除的结点p->next赋值给q;单链表标准删除语句,p->next = q->next;将q中数据赋值给e,作为返回;释放q结点;返回成功
Status DelLinkNode(LinkList  *L, int i, EleType *e)
{
    LinkList p, q;
    p = *L;
    int j;
    j = 1;
    while (p->next && j < i)
    {
        p = p->next;
        j++;

    }
    if (!(p->next) || j>i)
        return ERROR;
    q = p->next;
    p->next = q->next;
    *e = q->data;
    //让系统回收此节点,释放内存
    free(q);
    return OK;
}

//单链表的整表创建
//创建单链表的过程就是一个动态生成链表的过程
//单链表整表创建算法思路:声明一个指针p和计数器变量i;初始化一个空链表L;让L的头结点指针指向null,即创建一个带头结点的单链表;循环:生成一个新结点赋值给p,随机生成一个数字赋值给p的数据域p->data;将p插入到头结点与前一新节点之间。

#include<stdlib.h>
#include<time.h>
//头插法
void CreateListHead(LinkList *L,int n)
{
    LinkList p;
    int i;
    //初始化随机数种子
    srand(time(0));
    *L = (LinkList)malloc(sizeof(Node));
    (*L)->next = NULL;
    for (i = 0; i < n; i++)
    {
        p = (LinkList)malloc(sizeof(Node));
        p->data = rand() % 100 + 1;
        p->next = (*L)->next;
        (*L)->next = p;
    }
}

//尾插法
void CreateListTail(LinkList *L,int n)
{
    LinkList p, r;
    int i;
    r = (*L);
    for (i = 0; i < n; i++)
    {
        p = (LinkList)malloc(sizeof(Node));
        p->data = rand() % 100 + 1;
        r->next = p;
        r = p;
    }
    r->next = NULL; 
}

//单链表的整表删除
//单链表的整表删除的算法思路:声明一个节点p和q;将第一个结点赋值给p;循环:将下一个结点赋值给p;释放p;将q赋值给p;

Status ClearList(LinkList *L)
{
    LinkList p, q;
    p = (*L)->next;
    while (p)
    {
        q = p->next;
        free(p);
        p = q;
    }
    (*L)->next = NULL;
    return OK;
}

//单链表结构和顺序存储结构的优缺点:
//存储分配方式:顺序存储结构用一段连续的存储单元依次存储线性表的数据元素;单链表采用链式存储结构,用一组任意的存储樊元存放线性表的元素。
//时间性能:1.查找:顺序存储结构O(1),单链表O(n);2.插入和删除:顺序存储结构需要平均移动表长一样的元素,时间为O(n),单链表在线出某位置指针后,插入和删除时间仅为O(1)
//空间性能:顺序存储结构需要预分配存储空间,分大了浪费,分小了上溢;单链表存储结构不需要分配存储空间,只要有就可以分配,元素个数也不受限制

静态链表

//静态链表:数组描述的链表

//静态链表的存储结构
#define MAXSIZE 1000 //设置链表最大长度
typedef struct
{
    ElemType data;
    int cur;
}Component,StaticLinkList[MAXSIZE];

//初始化静态链表
Status InitList(StaticLinkList space)
{
    int i;
    for (i = 0; i < MAXSIZE - 1;i++)
    {
        space[i].cur = i + 1;
    }
    space[MAXSIZE-1].cur = 0;
    return OK;

}

//静态链表的插入操作:要解决的问题,如何用静态模拟动态链表的存储空间的分配,需要时申请,无用时释放

//若备用链表非空,则返回分配的结点下标,否则返回0
int Malloc_SLL(StaticLinkList space)
{
    int i = space[0].cur;
    if (space[0].cur)
    {
        space[0].cur = space[i].cur;
    }
    return i;
}

//静态链表的插入操作
Status InsertList(StaticLinkList space,int i,ElemType e)
{
    int j,k,l;
    if (i<1 || i>GetLinkLength(space) + 1)
        return ERROR;
    j = MAXSIZE - 1;
    l = Malloc_SLL(space);
    if (l)
    {
        space[l].data = e;
        for (k = 0; k < i - 1; k++)
            j = space[j].cur;
        space[l].cur=space[j].cur;
        space[j].cur = l;
        return OK;
    }

    return ERROR;
}

//计算静态链表中元素个数
int GetLinkLength(StaticLinkList L)
{
    int j = 0;
    int i = L[MAXSIZE - 1].cur;
    while (i)
    {
        j++;
        i = L[i].cur;
    }
    return j;
}

//回收空闲结点到备用链表
void Free_SSL(StaticLinkList space,int k)
{
    space[k].cur=space[0].cur;
    space[0].cur = k;
}
//静态链表的删除操作
Status DeleteLinkList(StaticLinkList L, int i)
{
    int j, k ;
    if (i<1 || i>GetLinkLength(L))
        return ERROR;
    j = MAXSIZE - 1;
    for (k = 1; k < i; k++)
        j = L[j].cur;
    L[j].cur = L[k].cur;
    Free_SSL(L,i);
    return OK;

}

//静态链表的优缺点:
//优点:在插入和删除操作时,只需要修改游标,不需要移动元素,从而改进了在顺序存储中的插入和删除操作需要移动大量数据的缺点。
//缺点:没有解决连续存储分配带来的表长难以确定的问题;失去了顺序存储结构随机存取的特性


循环链表

//合并两个链表
//p = rearA->next;
//rearA->next = realB->next->next;
//q = realB->next;
//realB->next = q;
//free(q);


双向链表

//线性表的双向链表存储结构
typedef struct DulNode
{
    ElemType data;
    struct DulNode *prior;//直接前驱指针;
    struct DulNode *next;//直接后驱指针;
}DulNode,*DuLinkList;

猜你喜欢

转载自blog.csdn.net/m0_37591671/article/details/78446374