数据结构第二天、线性表的链式表示和实现

  今天是学习数据结构的第二天,让我们来一起重温数据结构中极为经典的链表。

  在复习链表之前我们来复习一个C/C++中很重要的知识点

#include <stdio.h>
#include <stdlib.h>
typedef char ElemType;
typedef struct node
{
    ElemType data;
    struct node *next;
}LinkList;
void InitList(LinkList *L)//初始化单链表
{
    L=(LinkList *)malloc(sizeof(LinkList));
    L->next=NULL;
}
int main()
{
    int i;
    ElemType e;
    LinkList *L;
    InitList(L);
}

很多同学会说上述代码不就是完成链表初始化的一段代码吗,没有什么特殊的。其实,这段代码是会报错的。因为它根本没有初始化链表。

原因是InitList(L)实际上是对值的传递,和swap()函数的原理类似,传值调用传递的时原来数据的副本,副本是在栈上调用的,在函数执行完成后会自动释放,也没有返回到main函数的具体值,所以会失败。

正确方法是下面这种方法

#include <stdio.h>
#include <stdlib.h>
typedef char ElemType;
typedef struct node
{
    ElemType data;
    struct node *next;
}LinkList;
void InitList(LinkList **L)//初始化单链表
{
    *L=(LinkList *)malloc(sizeof(LinkList));
    (*L)->next=NULL;
}
int main()
{
    int i;
    ElemType e;
    LinkList *L;
    InitList(&L);
}

也就是传入指针的地址,即指针的指针。

在我的代码中,我才去了另外一种方法,即初始化函数返回时将指针赋值给main函数里的局部变量,这样也可以解决这种问题,具体代码如下:

#include <stdio.h>
#include <stdlib.h>

typedef struct Node
{
    int Data;
    struct Node *Next;
} List;

//创建具有头结点的链表
List *CreateList(int n)
{
    List *LinkList = (List *)malloc(sizeof(List));
    LinkList->Next = NULL;

    for (int i = n; i > 0; --i)
    {
        List *p = (List *)malloc(sizeof(List));
        scanf("%d", &p->Data);
        p->Next = LinkList->Next;
        LinkList->Next = p;
    }
    return LinkList;
}

//添加
void Insert(List *LinkList, int n, int e)
{
    List *p = LinkList;
    int j = 0;

    while (p && j < n-1) {
        p = p->Next;
        ++j;
    }

    if (!p || j > n-1)
    {
        printf("Error\n");
        return;
    }

    List *s = (List *)malloc(sizeof(List));
    s->Data = e;
    s->Next = p->Next;
    p->Next = s;
    return;
}

//删除
void Delete(List *LinkList, int n)
{
    List *p = LinkList;
    int j = 0;

    while (p->Next && j < n-1) {
        p = p->Next;
        ++j;
    }

    if (p->Next == NULL || j > n-1)
    {
        printf("Error\n");
        return;
    }

    List *q = p->Next;
    p->Next = q->Next;

    free(q);
    return;
}

//已知单链线性表La和Lb的元素按值非递减排列
//归并La和Lb得到新的单链线性表Lc,Lc也按值非递减排列
List *MergeList(List *la, List *lb)
{
    List *pa = la->Next;
    List *pb = lb->Next;
    List *lc = la;
    List *pc = lc;
    while (pa && pb) {
        if (pa->Data <= pb->Data)
        {
            pc->Next = pa;
            pc = pa;
            pa = pa->Next;
        } else {
            pc->Next = pb;
            pc = pb;
            pb = pb->Next;
        }
    }
    pc->Next = pa?pa:pb;
    free(lb);
    return la;
}

//遍历
void Traverse(List *LinkList)
{
    List *q = LinkList->Next;

    while (q != NULL) {
        printf("%d\n", q->Data);
        q = q->Next;
    }
    return;
}

int main(int argc, char const *argv[])
{
    List *list_link;
    list_link =  CreateList(4);
    printf("输出创建的链表\n");
    Traverse(list_link);
    //printf("%d\n", list_link->Next->Data);
    printf("输出删除具体节点后的链表\n");
    Delete(list_link, 2);
    Traverse(list_link);

    printf("输出la,lb归并后的链表测试\n");
    List *la, *lb, *lc;
    printf("请输入la链表\n");
    la = CreateList(3);
    printf("请输入lb链表\n");
    lb = CreateList(4);
    lc = MergeList(la, lb);
    Traverse(lc);
    return 0;
}

Insert()和Delete()的时间复杂度也都是O(n)量级的。

还有一个要主要的点是在做MergeList(归并操作)时,Lc链表只是将La和Lb链表中的节点重新链接在一起了,没有重新malloc空间。

时间: 2024-10-06 14:21:58

数据结构第二天、线性表的链式表示和实现的相关文章

【数据结构复习】线性表的链式存储--单链表

链表的重点概念: 数据域和指针域 头指针和头结点 下面是单链表的实现源码: // // main.c // DataStructure // // Created by SuooL on 15/5/22. // Copyright (c) 2015年 SuooL. All rights reserved. // #include "stdio.h" #include "string.h" #include "ctype.h" #include &

数据结构之线性表(链式存储结构)

线性表的实现分顺序存储结构和链式存储结构 上一节我们主要介绍了顺序存储结构,在最后我们还分别总结了顺序存储结构的优缺点, 对于顺序结构的缺点,我们有没有什么好的解决方法呢? 我们今天要介绍的线性表的链式存储结构就可以很好的解决顺序结构的缺点,一起来看. 顺序结构最大的缺点就是在进行插入和删除操作的时候,如果插入位置不理想,那么我们需要移动大量的元素,那产生这一问题的原因是什么呢? 仔细分析后,我们可以发现在顺序存储结构中,他们相邻的元素的存储位置也是相邻的,我们在申请内存的的时候,是一次性申请一

数据结构------线性表的链式表示与实现

不多说直接上代码: #include"stdafx.h" #include <stdio.h> #include <stdlib.h> /****************************************************************************** /* 数据类型和常量定义 /***********************************************************************

数据结构-线性表的链式结构

线性表的链式结构,与之前说过的线性表的顺序结构差不多,区别在于存储结构和方式的不一样. 在链式中,来一个数据就去寻找一个空间存储一个结点有多少数据占多大的地方,是动态的存储方式.另外顺序表如果存储1MB就只占1MB存储空间,但是链式表不一样,它会有额外的空间去存储对应结点的指针. 这样一分析结构就出来了,链式结构为两部分:1.结点域.2.指针域.实现方法用动态存储. 1 #include "stdio.h" 2 #include "stdlib.h" 3 4 typ

数据结构第三篇——线性表的链式存储之单链表

线性表的链式存储结构的特点是用一组任意的存储单元来存储线性表的数据元素,这些单元可以分散在内存中的任意位置上,其在物理上可以是连续的,也可以是不连续的.具有链式存储结构的线性表称为线性链表. 为了表示出每个数据元素与其后继之间的关系,除了存储数据元素本身的信息之外,还需存储指示其直接后继的信息.这可以用一个结点(node)来完整的表示. 将节点中存储数据元素本身信息的域称为数据域:存储其直接后继位置的域称为指针域.指针域中存储的信息称作指针或链. 一般情况下,链表中每个结点可以包含若干个数据域和

《数据结构 - 线性表》链式存储 (单链表)

一:线性表定义 -<数据结构 - 线性表>顺序存储结构 二:为什么要 链式存储 线性表? - 因为在使用 顺序结构 存储方式存储的时候,每次进行 插入/删除 都需要大量移动元素的位置. - 所以设计出一种 存储空间不连续 的存储结构. - 这个线性表可能是这样的(存储位置不固定) -  三:链式存储 定义 -  因为链式存储,不是连续空间,所以需要两个信息 - 一个用于 存储数据元素,也叫做 数据域 - 一个用于 指向 下一个位置 的 指示信息,叫做指针域. - 指针域中存储的信息叫指针/链

【数据结构】-线性表的链式存储结构

引言:由于线性表的顺序存储结构在插入和删除时需要大量移动数据元素,从而引入线性表的链式存储结构. 线性表的链式存储结构:用一组任意的存储单元(可以连续也可以不连续)存储线性表的数据元素. 为了表示数据元素ai和其直接后继ai+1之间的逻辑关系,对ai来说,除了存储其本身的数据信息外,还需要存储其直接后继的存储位置.这两部分信息组成数据元素ai的存储映像(结点).它包含两个域:其中存储数据元素信息的域称为数据域:存储直接后继存储位置的域称为指针域. n个结点链接成一个链表,称为线性链表,由于此链表

数据结构开发(5):线性表的链式存储结构

0.目录 1.线性表的链式存储结构 2.单链表的具体实现 3.顺序表和单链表的对比分析 4.小结 1.线性表的链式存储结构 顺序存储结构线性表的最大问题是: 插入和删除需要移动大量的元素!如何解决? 链式存储的定义: 为了表示每个数据元素与其直接后继元素之间的逻辑关系:数据元素除了存储本身的信息外,还需要存储其直接后继的信息. 链式存储逻辑结构: 基于链式存储结构的线性表中,每个结点都包含数据域和指针域 数据域:存储数据元素本身 指针域:存储相邻结点的地址 专业术语的统一: 顺序表 基于顺序存储

数据结构--线性表的链式存储结构

一 线性表的链式存储结构 A.链式存储的定义为了表示每个数据元素与直接后继元素之间的逻辑关系:数据元素除了存储本身的信息外,还需要存储其直接后继的信息图示B链式存储逻辑结构基于链式存储结构的线性表中,每个结点都包含数据域和指针域1.数据域:存储数据元素本身2.指针域:存储相邻结点的地址图示C链表中的基本概念1.头结点--链表中的辅助结点,包含指向第一个数据元素的指针(方便插入和删除)2.数据结点--链表中代表数据元素的结点,表现形式为:(数据元素,地址)3.尾节点--链表中的最后一个数据结点,包

线性表的链式存储

线性表的链式存储 线性表的链式存储 基本概念 设计与实现 实现代码 优缺点 1. 基本概念 链式存储定义 为了表示每个数据元素与其直接后继元素之间的逻辑关系,每个元素除了存储本身的信息外,还需要存储指示其直接后继的信息. 表头结点 链表中的第一个结点,包含指向第一个数据元素的指针以及链表自身的一些信息 数据结点 链表中代表数据元素的结点,包含指向下一个数据元素的指针和数据元素的信息 尾结点 链表中的最后一个数据结点,其下一元素指针为空,表示无后继. 2.设计与实现 在C语言中可以用结构体来定义链