【数据结构】知识点总结(C语言)

news2024/11/6 9:36:40

线性表栈和队列串、数组和广义表树和二叉树查找排序


线性表

线性表(顺序表示)

线性表是具有相同特性元素的一个有限序列,数据元素之间是线性关系,起始元素称为线性起点,终端元素称为线性终点。

线性表的顺序表示又称为顺序存储结构或者顺序映像。顺序存储的定义:把逻辑上相邻的数据元素存储在物理上相邻的存储单元中的存储结构。

顺序表的特点是:1、以物理位置表示相邻的逻辑关系;2、任意的元素均可以快速访问,故称为随机存取。

顺序表(Sequence List)的类型定义模板:

//顺序表定义模板
#define LIST_INIT_SIZE 100        //顺序表存储空间的初始分配
typedef struct {
    ElemType* elem;            //数据指针,动态分配存储空间
   int length;        //当前的长度
} SqList;

使用类型定义模板的案例:

//头文件包含
#include <stdio.h>
#include <stdlib.h>
//函数结果状态代码
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
//Status 是函数的类型,其值是函数结果状态代码
typedef int Status;
typedef char ElemType;
//顺序表的定义
#define MAXSIZE 100
typedef struct {
    ElemType* elem;
    int length;
} SqList;

//顺序表的初始化函数
Status InitList_Sq(SqList* L)
{
    L->elem = (ElemType*)malloc(MAXSIZE * sizeof(ElemType));
    if (!L->elem)
        exit(OVERFLOW);
    L->length = 0;
    return OK;
}
//销毁线性表
void DestroyList_Sq(SqList* L)
{
    if (L->elem)
        free(L->elem);
    L = NULL;
}
//清空线性表
void ClearList(SqList* L)
{
    L->length = 0;
}
//求线性表的长度
int GetLength(const SqList* L)
{
    return L->length;
}
//判断线性表是否为空
Status IsEmpty(const SqList* L)
{
    if (L->length == 0)
        return TRUE;
    else
        return FALSE;
}
//线性表取第i个值
Status GetElem(const SqList* L, int i, ElemType e)
{
    if (i<1 || i>L->length)
        return ERROR;
    else
    {
        e = L->elem[i - 1];
        return OK;
    }
}
//线性表按值顺序查找
Status LocateElem(const SqList* L, const ElemType e)
{
    int i;
    for (i = 0; i <= L->length - 1; i++)
    {
        if (L->elem[i] == e)
            return i + 1;        //查找成功返回元素位置
    }
    return 0;        //查找失败返回0
}
//顺序表的插入
Status InsertList_Sq(SqList* L, int n, const ElemType e)
{
    int i;
    if (n >= 1 && n <= L->length + 1)    //判断插入位置是否合法
    {
        if (L->length == MAXSIZE)        //判断存储空间是否已满
            return ERROR;
        for(i=L->length-1; i>=n-1; i--)        //插入位置及之后元素后移
        {
            L->elem[i+1] = L->elem[i];
        }
        L->elem[n - 1] = e;
        L->length += 1;
        return OK;
    }
    return ERROR;
}
//顺序表删除
Status DeleteElem(SqList* L, int n)
{
    int i;
    if (n >= 1 && n <= L->length)
    {
        L->elem[n - 1] = 0;        //删除指定元素
        for (i = n - 1; i <= L->length - 1; i++)        //剩余元素移位
        {
            L->elem[i] = L->elem[i + 1];
        }

        L->length--;        //顺序表长度-1
        return OK;
    }
    return ERROR;
}
//顺序表显示
void ShowList_Sq(const SqList* L)
{

    if (L->length == 0)
        puts("The SqList is empty!");
    
    else
    {
    int i;
    for (i = 0; i < L->length; i++)
    {
        printf("%d ", L->elem[i]);
    }
    putchar('\n');
    printf("The length of SqList is %d\n", L->length);

    }
}
//合并两个顺序表,将L2合并到L1中
Status MergeList_Sq(SqList* L1, const SqList* L2)
{
    if (L1->length == 0 || L2->length == 0)
    {
        puts("Length must be non-zero!");
        return ERROR;
    }
    else if (L1->length + L2->length > MAXSIZE)
    {
        puts("Overflow");
        return OVERFLOW;
    }
    else 
    {
        int i;
        for (i = 0; i <= L2->length - 1; i++)
        {
            L1->elem[i + L1->length] = L2->elem[i];
        }
        L1->length += L2->length;
        return OK;
    }
}
int main(void)
{
    SqList my_list;
    ElemType a, b, c, d, e, f;
    a = 1;
    b = 2;
    c = 3;
    d = 4;
    e = 5;
    f = 6;
    SqList my_list2;
    InitList_Sq(&my_list);
    InsertList_Sq(&my_list, 1, a);
    InsertList_Sq(&my_list, 2, b);
    InsertList_Sq(&my_list, 3, c);
    InsertList_Sq(&my_list, 1, d);
    InsertList_Sq(&my_list, 2, e);
    InsertList_Sq(&my_list, 3, f);
    //printf("%d\n", LocateElem(&my_list, a));
    //ShowList_Sq(&my_list);
    //DeleteElem(&my_list, 2);
    ShowList_Sq(&my_list);
    InitList_Sq(&my_list2);
    InsertList_Sq(&my_list2, 1, a);
    InsertList_Sq(&my_list2, 2, b);
    InsertList_Sq(&my_list2, 3, c);
    ShowList_Sq(&my_list2);
    MergeList_Sq(&my_list, &my_list2);
    ShowList_Sq(&my_list);
    return 0;
}
顺序表的优缺点
优点:1、存储密度大;2、可以随机存取表中任一元素。
缺点:1、在插入、删除某一元素时,需要移动大量其他元素;2、浪费大量存储空间;3、属于静态存储形式,数据元素的个数不能够自由扩充。

线性表(链式表示)

链式存储结构的特点
1、结点在存储器中的位置是任意的,即逻辑上相邻的数据元素在物理上不一定相邻。线性表的链式表示又称为非顺序映像或链式映像。
2、访问时只能通过头指针进入链表,并通过每个结点的指针域依次向后顺序扫描其余结点,所以寻找第一个结点和最后一个结点所花费的时间不等,这种存取元素的方式称为顺序存取。

链表(Link List)的分类:单链表、双链表、循环链表

a、单链表的实现
// 链表定义模板
typedef struct Lnode {
    ElemType data;
    struct Lnode* next;            //注意这里需要struct关键字
}Lnode, *LinkList;

单链表基本操作的实现

单链表实现完整算法

//头文件导入
#include <stdio.h>
#include <stdlib.h>
//函数结果状态代码
#define OK 1
#define ERROR 0
//Status 是函数的类型,其值是函数结果状态代码
typedef int Status;
typedef int ElemType;
//单链表
typedef struct Signle_Link_List{
    ElemType data;
    struct LNode* next;
} LNode, *LinkList;

//创建空链表
Status InitLinkList(LinkList* L)
{
    *L = (LinkList)malloc(sizeof(LNode));
    if (*L == NULL)
        return ERROR;
    (*L)->next = NULL;
    return OK;
}
//判断链表是否为空
int IsEmptyLinkList(const LinkList* L)
{
    if ((*L)->next == NULL)
        return 1;
    else
        return 0;
}
//单链表的销毁
Status DestoryLinkList(LinkList* L)
{
    LNode* p;
    while (*L != NULL)
    {
        p = *L;
        *L = (*L)->next;
        free(p);
    }
    return OK;
}
//清空单链表
Status ClearLinkList(LinkList* L)
{
    LNode* p, * q;
    q = (*L)->next;
    while (q != NULL)
    {
        p = q;
        q = q->next;
        free(p);
    }
    (*L)->next = NULL;
    return OK;
}
//求单链表的表长
int LenLinkList(const LinkList* L)
{
    LNode* p;
    p = (*L)->next;
    int i = 0;
    while (p)
    {
        i++;
        p = p->next;
    }
    (*L)->data = i;            //将长度存储到L头结点的数据域中
    return i;
}
//取出单链表中第i个元素
Status LocateElem(const LinkList *L, int i, ElemType *e)
{
    int j = 1;
    LNode* p;
    p = (*L)->next;
    while (p && j < i)
    {
        j++;
        p = p->next;
    }
    if (!p || j > i)        //如果待查找的元素大于链表长度或者小于1,查找错误
        return ERROR;
    *e = p->data;
    return OK;
}
//单链表按值查找,返回LNode
LNode* LocateElem_V_LNode(const LinkList *L, ElemType value)
{
    LNode* p;
    p = (*L)->next;
    while (p && p->data != value)        //p不为空指针,并且没找到
    {
        p = p->next;
    }
    return p;            //找到返回结点的地址,没找到返回NULL
}
//单链表按值查找,返回元素位置
int LocateElem_V_Index(const LinkList *L, ElemType value)
{
    int j = 1;
    LNode* p;
    p = (*L)->next;
    while (p && p->data != value)
    {
        j++;
        p = p->next;
    }
    if (!p)
        return 0;        //没找到,返回0
    else
        return j;        //找到,返回第几个结点
}
//单链表插入,在第i个结点之前插入一个结点
Status InsertLinkList(LinkList *L, int i, ElemType value)
{
    LNode* p;
    p = (*L)->next;
    int j = 1;
    while (p && j < i - 1)        //找到第i-1个结点
    {
        j++;
        p = p->next;
    }
    if (!p || j > i - 1)        //i大于表长+1,或者小于1,插入位置非法
        return ERROR;

    LNode* newlnode;
    newlnode = (LNode*)malloc(sizeof(LNode));
    newlnode->data = value;
    newlnode->next = p->next;
    p->next = newlnode;
    return OK;
}
//单链表删除,删除第i个结点
Status DeleteLinkList(LinkList *L, int i)
{
    LNode* p, * q;
    int j = 1;
    p = (*L)->next;
    while (p && j < i - 1)
    {
        j++;
        p = p->next;
    }
    if (!p || j > i - 1)
        return ERROR;

    q = p->next;
    p->next = q->next;
    free(q);
    return OK;
}
//单链表建立-头插法
void CreateLinkList_H(LinkList* L, int n)
{
    *L = (LinkList)malloc(sizeof(LNode));
    (*L)->next = NULL;                    //先建立一个头结点
    int i;
    for (i = n; i > 0; i--)
    {
        LNode* newlnode;
        newlnode = (LNode*)malloc(sizeof(LNode));
        printf("Enter the node data:_____\b");
        scanf("%d", &newlnode->data);
        newlnode->next = (*L)->next;
        (*L)->next = newlnode;
    }
}
//单链表建立-尾插法
void CreateLinkList_R(LinkList *L, int n)
{
    *L = (LinkList)malloc(sizeof(LNode));
    (*L)->next = NULL;                    //先建立一个头结点
    LNode* p;
    p = *L;
    int i;
    for (i = n; i > 0; i--)
    {
        LNode* newlnode;
        newlnode = (LNode*)malloc(sizeof(LNode));
        printf("Enter the node data:___\b");
        scanf("%d", &newlnode->data);
        newlnode->next = NULL;
        p->next = newlnode;
        p = p->next;
    }
}
//显示单链表
void ShowLinkList(const LinkList* L)
{
    LNode* p;
    p = (*L)->next;
    if (!p)
    {
        puts("The LinkList is empty");
        return;
    }
    int i = 1;
    while (p)
    {
        printf("%d : %d\n", i, p->data);
        i++;
        p = p->next;
    }
    putchar('\n');
}
//测试函数
int main(void)
{
    LinkList my_list;
    my_list = NULL;
    ElemType answer = 0;
    //InitLinkList(my_list);
    //CreateLinkList_H(&my_list, 3);        //测试头插法建立链表
    CreateLinkList_R(&my_list, 3);            //测试尾插法建立链表
    //ClearLinkList(&my_list);                //测试清空链表
    ShowLinkList(&my_list);
    //DestoryLinkList(&my_list);                //测试销毁链表
    printf("%s\n",IsEmptyLinkList(&my_list) >0?
        "LinkList is Empty":"LinkList isn't Empty");        //测试判断链表函数
    printf("The length of LinkList is %d\n", LenLinkList(&my_list));        //测试求长度函数
    LocateElem(&my_list, 3, &answer);
    printf("The %d elem is %d\n", 3, answer);        //测试取元素函数
    LNode *answer1;
    answer1 = LocateElem_V_LNode(&my_list, 2);
    printf("The answer is %d\n", answer1->data);        //测试取元素函数
    printf("The Index of 3 is %d\n", LocateElem_V_Index(&my_list, 3));            //测试取元素函数
    InsertLinkList(&my_list, 2, 10);        //测试增加结点函数
    ShowLinkList(&my_list);
    DeleteLinkList(&my_list, 3);            //测试删除结点函数
    ShowLinkList(&my_list);                    
    return 0;
}
b、单向循环链表的实现
c、双向链表的实现
//双向链表的定义
typedef struct DuLNode {
    ElemType data;
    struct DuLNode* prior, * next;
} DuLNode, *DuLinkList;

双向链表的操作

  1. 双向链表的插入

  1. 双向链表的删除

d、双向循环链表的实现
链表的优缺点

各种链表的比较

栈和列队

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/374630.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python线程通信

在现实生活中&#xff0c;如果一个人团队正在共同完成任务&#xff0c;那么他们之间应该有通信&#xff0c;以便正确完成任务。 同样的比喻也适用于线程。 在编程中&#xff0c;要减少处理器的理想时间&#xff0c;我们创建了多个线程&#xff0c;并为每个线程分配不同的子任务…

线上监控诊断神器arthas

目录 什么是arthas 常用命令列表 1、dashboard仪表盘 2、heapdump dumpJAVA堆栈快照 3、jvm 4、thread 5、memory 官方文档 安装使用 1、云安装arthas 2、获取需要监控进程ID 3、运行arthas 4、进入仪表盘 5、其他命令使用查看官方文档 什么是arthas arthas是阿…

【自然语言处理】BERT GPT

BERT & GPT近年来&#xff0c;随着大规模预训练语言模型的发展&#xff0c;自然语言处理领域发生了巨大变革。BERT 和 GPT 是其中最流行且最有影响力的两种模型。在本篇博客中&#xff0c;我们将讨论 BERT 和 GPT 之间的区别以及它们的演变过程。 1.起源 201820182018 年&a…

2023软件测试现状,点工如何破局成为卷王····

近几年来的特殊情况&#xff0c;综合过去的大形势变化&#xff0c;所有行业都会自下而上的进行一轮技术“大清洗”&#xff0c;技术停滞不前的“点工”或将被逐步取代。 软件测试现状 测试行业在十几年间发生了翻天覆地的变化&#xff0c;从早期站在风口上的快速发展&#xf…

【mybatis】 01- mybatis快速入门

数据库创建(注意&#xff1a;最好先创建好数据库设置utf8再进行表创建) create database mybatis; use mybatis;drop table if exists tb_user;create table tb_user(id int primary key auto_increment,username varchar(20),password varchar(20),gender char(1),addr varch…

【数据结构】初识二叉树(二叉树的入门知识)

初识二叉树一、树概念及结构1、树的概念2、树的相关概念3、树的表示4、树在实际中的运用&#xff08;表示文件系统的目录树结构&#xff09;二、二叉树概念及结构1、概念2、特殊的二叉树3、二叉树的性质4、二叉树的存储结构三、结语一、树概念及结构 1、树的概念 树是一种非线…

【win10网络重置后,网络适配器消失或者不能使用】

注&#xff1a;此文章为重新整理的版本&#xff0c;旧版本&#xff1a;https://blog.csdn.net/Viwise/article/details/123263847?spm1001.2014.3001.5502 目录 一、问题描述 【总结】 【过程】 二、方法 1、针对设备问题代码为56的解决方法&#xff1a;安装CCleaner &am…

建模算法整理

优化 改进的蝙蝠算法 2022 E 2218144 使用背景&#xff1a;将每年砍伐树木比例定义为n&#xff0c;每年树木种植比例定义为m&#xff0c;设置一系列指标以及指标的加权计算方法&#xff08;即函数F(X)的设定&#xff09;&#xff0c;寻找最优的n,m。 蝙蝠算法主要用于目标函数…

算法leetcode|38. 外观数列(多语言实现)

文章目录38. 外观数列&#xff1a;样例 1&#xff1a;样例 2&#xff1a;提示&#xff1a;分析&#xff1a;题解&#xff1a;rustgocpythonjava38. 外观数列&#xff1a; 给定一个正整数 n &#xff0c;输出外观数列的第 n 项。 「外观数列」是一个整数序列&#xff0c;从数字…

【C++】map和set的封装(红黑树)

map和set的封装一、介绍二、stl源码剖析三、仿函数获取数值四、红黑树的迭代器五、map的[]5.1 普通迭代器转const迭代器六、set源码七、map源码八、红黑树源码一、介绍 首先要知道map和set的底层都是用红黑树实现的 【数据结构】红黑树 set只需要一个key&#xff0c;但是map既…

分布式-分布式消息笔记

消息队列应用场景 消息队列 消息队列是进程之间的一种很重要的通信机制。参与消息传递的双方称为生产者和消费者&#xff0c;生产者和消费者可以只有一个实例&#xff0c;也可以集群部署。 消息体是参与生产和消费两方传递的数据&#xff0c;消息格式既可以是简单的字符串&am…

MYSQL安装部署 - Linux 本地安装及卸载

声明 &#xff1a;# 此次我们安装的 MYSQL 版本是 8.0.32 版本我们本次安装 MYSQL 总共要介绍 四种方式# 仓库安装# 本地安装# 容器安装# 源码安装我们本篇介绍的是 本地安装 我们还是去官网下载 &#xff1a;我们就是找着 .bundle.tar 这个包&#xff0c;里面就包含了所有 mys…

功率信号源有什么作用和功能呢

功率信号源是指集信号发生器与功率放大器为一体的电子测量仪器&#xff0c;它具有高电压、大功率的特点&#xff0c;在电子实验室中能够帮助用来驱动压电陶瓷、换能器以及电磁线圈等&#xff0c;可以有效的帮助电子工程师解决驱动负载和放大功率的问题。功率信号源和功率放大器…

过滤器,监听器,拦截器的原理与在Servlet和Spring的应用

在Java Web的开发中&#xff0c;最原始和初期的学习都是从Servlet开始的&#xff0c;Servlet是Java最为耀眼的技术&#xff0c;也是Java EE的技术变革。目前大火主流的框架spring boot也的spring mvc部分也是基于拓展servlet完成的。回到之前的文章spring 实现了对servlet的封装…

SQL语句大全(详解)

SQL前言1 DDL1.1 显示所包含的数据库1.2 创建数据库1.3 删除数据库1.4 使用数据库1.4.1 创建表1.4.2 查看表的结构1.4.3 查看当前数据库下的所有表1.4.4 基础的增删改查1.4.4.1 删除表1.4.4.2 添加列1.4.4.3 修改表名1.4.4.4 修改数据类型1.4.4.5 修改列名和数据类型2 DML2.1 给…

http协议简介

http 1.简介 超文本传输协议&#xff08;HTTP&#xff0c;HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。所有的WWW文件都必须遵守这个标准。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。1960年美国人Ted Nelson构思了一种通过计算机处…

Python实现GWO智能灰狼优化算法优化循环神经网络分类模型(LSTM分类算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。1.项目背景灰狼优化算法(GWO)&#xff0c;由澳大利亚格里菲斯大学学者 Mirjalili 等人于2014年提出来的一种群智能优…

【玩转c++】git的安装和使用以及可视化处理

本期主题&#xff1a;git的安装和使用&#xff08;windows环境&#xff09;博客主页&#xff1a;小峰同学分享小编的在Linux中学习到的知识和遇到的问题 小编的能力有限&#xff0c;出现错误希望大家不吝赐1.两个工具介绍第一个工具git&#xff0c;链接gitee或者github等代码托…

B端产品经理如何做好客户访谈?

用户访谈的价值我们在做用户研究的时候&#xff0c;经常会采用问卷调查和数据分析等定量的研究方法&#xff0c;从中我们可以搜集很多有价值的数据。但是&#xff0c;这些数据往往只停留在表层&#xff0c;没有办法基于用户的场景了解用户行为动机及诉求&#xff0c;很难找到用…

MySql的安装

版本选择 MySql目前使用最稳定的版本为5.7系列版本,尝鲜可以直接去官网链接整最新版本哦 本文使用8.0.32版本,注意这里看一下电脑位数,现在个人电脑一般都是64bit 点击223.6M那个压缩包开始下载,下面那个压缩包包含了测试相关内容一般是不需要的 这里有时会提示要你登录账户…