数据结构与算法(C语言)之线性表(连式存储结构)

1.线性表的链式存储结构是用一组任意的存储单元存储线性表的数据元素,这组存储单元可以存在内存中未被占用的任意位置。

 线性表的连式存储结构包括数据域和指针域;其中数据域存放数据元素信息指针域存放指针,我们把这两部分信息组成的数据元素称为结点(Node)

2.

ADT LinkList

Data

数据结构包括两部分,一部分用来存放数据,另一部分用来存放指向下一个结构的指针。

Operation

GetElem(L,i,*e):单链表的读取

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

ListInsert(*L,i,e):单链表的插入

只需让s->next和p->next的指针做一点的改变。
    -s->next=p->next;
    -p->next=s;

ListDelete(*L,i,*e):单链表的删除

假设元素a2的结点为q,要实现结点q删除单链表的操作,其实就是将它的前继结点的指针绕过指向后继结点即可
    -p->next=p->next->next;
    -或q=p->next;p->next=q->next;
    单链表第i个数据删除结点的算法思路:
        -声明结点p指向链表第一个结点,初始化j=1;
        -当j<1时,就遍历链表,让p的指针向后移动,不断指向下一个结点,j累加1;
        -若到链表末尾p为空,则说明第i个元素不存在;
        -否则查找成功,将欲删除结点p->next赋值给q;
        -单链表的删除标准语句p->next=q->next;
        -将q结点中的数据赋值给e,作为返回;
      -释放q结点

CreateListHead(*L,n):单链表的创建

一个动态生成链表的过程,从“空表”的初始状态起,依次建立各元素结点并逐个插入链表
    -声明一个结点p和计数器变量i
    -初始化一空链表L;
    -让L的头结点的指针指向NULL,即建立一个带头结点的单链表;
   -循环实现后继结点的赋值和插入。

头插法建立单链表:
头插法从一个空表开始,生成新结点,读取数据存放到新结点的数据域中,然后将新结点插入到当期链表的表头上,直到结束为止。
简单来说,就是包新加进的元素放在表头后的第一个位置:
    -先让新结点的next指向头结点之后
    -然后让表头的next指向新结点

CreateListTail(*L,n)

尾插法建立单链表:
头插法建立的链表的结点的次序和输入的顺序相反。
单链表的尾插法思路如下:
    -创建一个链表的头指针
    -用两个指针变量依次循环向下插入结点

ClearList(*L):单链表的整表删除

单链表整表删除的算法思路如下:
    -声明结点p和q
    -将第一个结点赋值给p,下一个结点赋值给q;
    -循环执行释放p和q赋值给p的操作

3.实现

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/**
 线性表的链式存储结构是用一组任意的存储单元存储线性表的数据元素
 ,这组存储单元可以存在内存中未被占用的任意位置。
 线性表的连式存储结构包括数据域和指针域;其中数据域存放数据元素信息
 指针域存放指针,我们把这两部分信息组成的数据元素称为结点(Node)

 */
#define OK 1
#define ERROR 0
typedef int Status;
 typedef int ElemType;
 typedef struct Node
 {
     ElemType data;
     struct Node* next;
 }Node;
 typedef struct Node* LinkList;
 /*
 单链表的读取
 获得链表第i个数据的算法思路:
    -声明一个结点p指向链表第一个结点,初始化j从1开始;
    -当j<i时,就遍历链表,让p的指针向后移动,不断指向下一个结点,j+1
    -若到链表末尾p为空,则说明第i个元素不存在;
    -否则查找成功,返回结点p的数据。
 */
 Status GetElem(LinkList L,int i,ElemType *e)
 {
     int j=1;
     LinkList p;

     p=L->next;

     if(!p || j>i)
        return ERROR;
     while(p && j<i)
     {
         p=p->next;
         ++j;
     }
     *e=p->data;
     return OK;
 }
 /*
 单链表的插入:
 只需让s->next和p->next的指针做一点的改变。
    -s->next=p->next;
    -p->next=s;
 */
 Status ListInsert(LinkList *L,int i,ElemType e)
 {
     int j=1;
     LinkList p,s;

     p=*L;

     if(!p || j>i)
        return ERROR;
     while(p&&j<i)
     {
         p=p->next;
         j++;
     }
     s=(LinkList)malloc(sizeof(Node));
     s->data=e;
     s->next=p->next;
     p->next=s;

     return OK;
 }
 /*
 单链表的删除:
    假设元素a2的结点为q,要实现结点q删除单链表的操作,其实就是将它的前继结点的指针绕过指向后继结点即可
    -p->next=p->next->next;
    -或q=p->next;p->next=q->next;
    单链表第i个数据删除结点的算法思路:
        -声明结点p指向链表第一个结点,初始化j=1;
        -当j<1时,就遍历链表,让p的指针向后移动,不断指向下一个结点,j累加1;
        -若到链表末尾p为空,则说明第i个元素不存在;
        -否则查找成功,将欲删除结点p->next赋值给q;
        -单链表的删除标准语句p->next=q->next;
        -将q结点中的数据赋值给e,作为返回;
        -释放q结点

 */
 Status ListDelete(LinkList *L,int i,ElemType *e)
 {
     int j=1;
     LinkList p,q;

     p=*L;

     if(!(p->next)||j>i)
        return ERROR;

     while((p->next)&&j<i)
     {
         p=p->next;
         ++j;
     }
     q=p->next;
     *e=q->data;
     p->next=q->next;
     free(q);

     return OK;
 }
 /*
 单链表的创建:
 一个动态生成链表的过程,从“空表”的初始状态起,依次建立各元素结点并逐个插入链表
    -声明一个结点p和计数器变量i
    -初始化一空链表L;
    -让L的头结点的指针指向NULL,即建立一个带头结点的单链表;
    -循环实现后继结点的赋值和插入。
 */
/*
头插法建立单链表:
头插法从一个空表开始,生成新结点,读取数据存放到新结点的数据域中,然后将新结点插入到当期链表的表头上,直到结束为止。
简单来说,就是包新加进的元素放在表头后的第一个位置:
    -先让新结点的next指向头结点之后
    -然后让表头的next指向新结点
*/
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;

    srand(time(0));
    *L=(LinkList)malloc(sizeof(Node));

    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,下一个结点赋值给q;
    -循环执行释放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.存储分配方式
    -顺序存储结构用一段连续的存储单元依次存储线性表的数据元素
    -单链表采用链式存储结构,用一组任意的存储单元存放线性表的元素
2.时间性能
    -查找
        顺序存储结构O(1)
        单链表O(n)
    -插入和删除
        顺序存储结构需要平均移动表长一半的元素,时间为O(n)
        单链表在计算出某位置的指针后,出入和删除时间仅为O(1)
    -空间性嫩
        若线性表需要频繁查找,很少进行插入和删除操作是,宜采用顺序存储结构。
        若需要频繁插入和删除时,宜采用单链表结构
*/
int main()
{
    printf("Hello world!\n");
    return 0;
}



4.单链表结构与顺序存储结构的优缺点

1.存储分配方式
    -顺序存储结构用一段连续的存储单元依次存储线性表的数据元素
  -单链表采用链式存储结构,用一组任意的存储单元存放线性表的元素
2.时间性能
    -查找
        顺序存储结构O(1)
        单链表O(n)
    -插入和删除
        顺序存储结构需要平均移动表长一半的元素,时间为O(n)
        单链表在计算出某位置的指针后,出入和删除时间仅为O(1)
    -空间性嫩
        若线性表需要频繁查找,很少进行插入和删除操作是,宜采用顺序存储结构。
        若需要频繁插入和删除时,宜采用单链表结构










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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yiluohan0307

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值