大话数据结构笔记3-2:链表

静态链表 (游标实现法)

数组描述的链表,每个数组由 data(数据域)存放数据元素和cur(指针域)存放后继元素的下标 组成
第一个和最后一个元素不存数据,第一个元素存放备用链表第一个结点的下标,最后一个元素cur存放第
一个有数值的元素的下标

备用链表

未被使用的数组元素称为备用链表
大话数据结构笔记3-2:链表_第1张图片

下图中元素0的cur为7,因为第一个备用链表的下标是7
最后一个元素的cur是1 ,因为第一个不为空的节点是1
大话数据结构笔记3-2:链表_第2张图片

静态链表的插入

静态链表操作的是数组,不存在动态链表的结点申请和释放问题,需要手动实现

#include "stdio.h"

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

//静态链表 把长度设大一些
#define MAXSIZE 1000
typedef int Status;
typedef int EleType; //EleType 根据情况而定 此处 int

//线性表的单链存储结构
typedef struct
{
    EleType data;
    int cur;
} Component, StaticLinkList[MAXSIZE];


//初始化 静态链表
Status InitList(StaticLinkList space)
{
    int i;
    for (i = 0; i < MAXSIZE - 1; i++)
        space[i].cur = i + 1;
    //空链表  最后一个元素指向0
    space[MAXSIZE - 1].cur = 0;
    return OK;
}

//分配一个结点,若备用空间链表非空,则返回分配的结点下标,否在返回0
int Malloc_SSL(StaticLinkList space)
{
    int i = space[0].cur;

    if (space[0].cur)
        space[0].cur = space[i].cur;

    return i;
}
//释放一个结点到备用链表
void Free_SSL(StaticLinkList space, int k)
{
    //结点k指向第一个
    space[k].cur = space[0].cur;
    space[0].cur = k;
}

//获取链表长度
int ListLength(StaticLinkList L)
{
    int j;
    int i = L[MAXSIZE - 1].cur;
    while (i)
    {
        i = L[i].cur;
        j++;
    }
    return j;
}

//在第i个元素之前插入元素e
Status ListInsert(StaticLinkList L, int i, EleType e)
{
    int j, k, l;
    k = MAXSIZE - 1;
    if (i < 1 || i > ListLength(L) + 1)
        return ERROR;
    j = Malloc_SSL(L);
    if (!j)
        return ERROR;

    L[j].data = e;

    //找出第i个元素的前一个元素
    for (l = 1; l < i; l++)
        k = L[k].cur;
    L[j].cur = L[k].cur;
    L[k].cur = j;

    return OK;
}

//删除第i个元素
Status ListDelete(StaticLinkList L, int i)
{
    int j,k;
    k = MAXSIZE-1;
    for(j = 1; j<i;j++)
        k = L[k].cur;
    j = L[k].cur;//第i个元素
    L[k].cur = L[j].cur;//指向i的下一个元素
    Free_SSL(L, j);

    return OK;
}


Status ListPrint(StaticLinkList L)
{
    int j = 0;
    int i = L[MAXSIZE - 1].cur;
    while (i)
    {
        visit(L[i].data);
        i = L[i].cur;
        j++;
    }
    return j;
    printf("\n");
    return OK;
}
Status visit(EleType c)
{
    printf("%c ",c);
    return OK;
}

int main()
{
    StaticLinkList L;
    Status i;
    i = InitList(L);
    printf("静态链表L的长度L.length=%d\n", ListLength(L));

    i = ListInsert(L, 1, 'F');
    i = ListInsert(L, 1, 'E');
    i = ListInsert(L, 1, 'D');
    i = ListInsert(L, 1, 'B');
    i = ListInsert(L, 1, 'A');

    printf("\n L的数据\nL.data=");
    ListPrint(L);

    i = ListInsert(L, 3, 'C');
    printf("\n位置3 插入C\nL.data=");
    ListPrint(L);

    i=ListDelete(L,1);
    printf("\n删除第一个元素\nL.data=");
    ListPrint(L);

    printf("\n");

    return 0;
}

静态链表的优缺点

大话数据结构笔记3-2:链表_第3张图片

循环链表

将单链表的终端节点的指针由 空指针 改为指向头结点,就形成了头尾相接的单链表,称为单循环链表,简称循环链表
解决了如何从某一个节点出发, 遍历整个链表。

双向链表

在单链表的每个结点中,再设置一个指向其前驱结点的指针域。即双向链表的结点有两个指针域,指向前驱和指向后继
typedef struct DulNode 
{
    EleType data;
    struct DulNode *pre;
    struct DulNode *next;
} DulNode, *DuLinkList;

大话数据结构笔记3-2:链表_第4张图片

双向链表的插入

将结点s, 插入到 p和p->next 之间
大话数据结构笔记3-2:链表_第5张图片

	s->pre = p;
	s->next = p->next;
	p->next->pre = s;
	p->next = s
	

双向链表的删除

删除结点p
大话数据结构笔记3-2:链表_第6张图片

p->next->pre = p->pre;
p->pre->next = p->next;
free(p)

线性表总结

  • 顺序存储:使用一段地址连续的存储单元依次存储线性表的数据元素, 如数组
  • 链式存储: 不收固定的存储空间限制,方便插入和删除
    大话数据结构笔记3-2:链表_第7张图片

你可能感兴趣的:(大话数据结构笔记)