【数据结构】期中考试一把梭(通宵版上)

简介: 【数据结构】期中考试一把梭(通宵版上)

前言


红中(Hong_zhong)
CSDN内容合伙人、2023年新星计划web安全方向导师、
吉林师范大学网安大一的一名普通学生、摸鱼拿过大挑校二、
华为MindSpore截至目前最年轻的优秀开发者、IK&N战队队长、
阿里云专家博主、华为网络安全云享专家、腾讯云自媒体分享计划博主、


链表


链表的初步印象


链表,即链式存储结构。

DATA是咱自定义的数据类型,NEXT为指向下一个链表的指针。当我们访问NEXT时,被引导到链表下一个节点的位置。


抽象点就类似于火车车厢

一节车厢前面是节点,后面是指针,中间连接即指针指向的位置。


链表与数组的差别


那这玩意相较于数组,插入删除等操作变得更加容易。


为啥这么说捏?


打个比方,现在有这样一个数组:


[1,2,3,4,5,6,7,8]


我想在“1”之后插入一个”9“,那就意味着”1“之后的所有元素都需要向后挪一位,然后再整一块新的内存空间,把”9“塞里。麻烦死


但如果是链表,先抽象说说,想在火车车厢间加一节,只需要把车厢之间的链子解开,后面的先挂到新车厢上,前面再挂,完事了。


不需要整体/大部分数据去调整,改变指针所指向的DATA就行了,确实方便。


不过这玩意占用相较于数组大了不只一点


链表常见类型


单链表、双链表、循环单链表

图片来源:一口气搞懂「链表」,就靠这20+张图了 - 知乎


单链表


单链表概念的代码表述:

typedef struct Node{//定义单链表的结点类型
    int data;//数据域,随便写哪种类型都可以
    struct Node *next;//指针域
    }Node,*LinkList;//Node表示结点的类型,LinkedList表示指向Node结点类型的指针类型


链表的初始化


LinkedList listinit(){
    Node *L;
    L=(Node*)malloc(sizeof(Node));//申请开辟空间
    if(L==NULL){
        printf("申请失败");//判断是否开辟成功
    }
    L->next=NULL;//指针指向NULL
}

申请开辟空间那块咱也不到是啥,背下来就完了。


头插法


这玩意其实挺好理解的

这是一个节点,头插即从头插。假设我再来一个节点,即可以把新节点的指针指向原节点的DATA处。原节点始终排在后面,即到最后整条链表的顺序为倒序。


代码实现:

LinkedList LinkedListCreate(){
    Node *L;
    L=(Node *)malloc(sizeof(Node));
    L->next=NULL;
    int x;//x为链表中的数据
    while (scanf("%d",&x!=EOF)){
        Node *p;//定义p的指针域
        p=(Node *)malloc(sizeof(Node));//申请空间
        p->data=x;//将x赋给p节点的数据域
        p->next = L->next;//将头指针所指向的下一个结点的地址,赋给新创建结点的next 
        L->next = p;//将新创建的结点的地址赋给头指针的下一个结点
       }
    return L;
}


尾插法


尾插法同样的理解,原节点的指针指向新节点的DATA域。


不解释,直接写代码:

LinkedList LinkedListCreate(){
    Node *L;//申请指针域
    L=(Node *)malloc(sizeof(Node));//申请头节点空间
    L->next=NULL;//初始化一个空链表
    Node *r;
    r=L;//r始终指向尾节点,开始时指向头节点
    int x;//x为链表DATA中的数据
    while (scanf("%d",&x)!=EOF){
        Node *p;//申请指针域
        p=(Node *)malloc(sizeof(Node));//申请新的节点
        p->data=x;
        r->next=p;
        r=p;//r始终指向尾节点
    }
    r=next=NULL;
    return L;
}


修改


LinkedList LinkedListReplace(LinkedList L,int a,int b) {
    Node *p=L->next;//定义指针域指向节点指针指向
    int i=0;
    while(p){
        if(p->data==a){//如果p节点数据域中的值等于a
            p->data=b;//将p节点数据域中的值a改成b
        }
        p=p->next;//节点指针依旧指向后面
    }
    return L;
}


插入


LinkedList LinkedListInsert(LinkedList L,int i,int x) {
    Node *pre;                      //pre为前驱结点
    pre = L;
    int tempi = 0;
    for (tempi = 1; tempi < i; tempi++) {
        pre = pre->next;                 //查找第i个位置的前驱结点
    }
    Node *p;                                //插入的结点为p
    p = (Node *)malloc(sizeof(Node));
    p->data = x;//给p赋个值
    p->next = pre->next;//将前驱节点之前指向的地址赋给插入节点并让其指向
    pre->next = p;//将前驱节点指针指向引导到新节点头上
    return L;
}


删除


LinkedList LinkedListDelete(LinkedList L,int x) {
    Node *p,*pre; //pre为前驱结点,p为查找的结点。
    p = L->next;
    while(p->data != x) {//查找值为x的元素
        pre = p;
        p = p->next;
    }
    pre->next = p->next;//删除操作,将其前驱next指向其后继。
    free(p);//free函数释放掉
    return L;
}


习题


第一题、第二题:随便举几个推值代数。


第三题直接带。第四题看图嘛

第五题:涉及概念


存储密度,在计算机中是指结点数据本身所占的存储量和整个结点结构所占的存储量之比,计算公式:存储密度 = (结点数据本身所占的存储量)/(结点结构所占的存储总量)


第六题:顺序表简单了解下

第十/十一题:带头单链表就是指针域指向空,不带头就自己是空。


感觉没啥好讲的,直接填空看看

简单过过知识点,没啥难点



原理/概念


之前学过Python的栈,简单聊聊原理,看看代码实现,做点题就过了。


刚开始书架是空的,我们放里面一本《母猪的产后护理》,好,栈内已经有一本书了


现在我们再往里放一本《我是如何因为CTF毁掉自己人生的》,现在栈内有两本书

栈这个东西类似于一个桶形书架。


如果我们想看《母猪的产后护理》,又不能直接从栈底抽出来,就只能先把《我是如何因为CTF毁掉自己人生的》拿出来,再得到我们想要的书。


那这里的顺序就是一个栈的特性:先进后出


反正我就记得这一个,再说也说不了啥了,看代码实现。


代码实现


不难


置空栈


void InitStack(SeqStack *S){
    S->top=-1;
}


判定栈空否


int EmptyStack(SeqStack * S){
    if (S->top<0)
        return 1;//为空栈
    else
        return 0;//不为空栈
}


进栈


int Push(SeqStack * S,DataType x){
    if (S->top>=MAXSIZE-1)//
    {    printf("栈满不能进栈");
         return 0;
    }
    S->top++;//移动栈顶指针
    S->data[S->top]=x;//元素x进栈
    return (1);
}


出栈


和入栈差不多嘛

int Push(SeqStack * S){
    if (S->top《=MAXSIZE-1)//
    {    printf("栈空不能出栈");
         exit(0);
    }
    x=S->data[S->top]//将栈顶值保存至x
    S->top--;//移动栈顶指针
    return (x);
}


读取栈顶元素


DataType GetTop(LinkStack * Top)
{
    if (Top == NULL)
        printf("\n栈空");
    else
        return Top->data;
}

完整代码及示例:

#include<bits/stdc++.h>
using namespace std;
#define MaxSize 100 //定义栈中元素的最大个数
typedef struct SqStack{
    int data[MaxSize]; //存放栈中的元素
    int top; //栈顶指针
}SqStack;
//初始化
void InitStack(SqStack &S){
    S.top = -1;
}
//判栈空
bool Empty(SqStack S){
    if(S.top == -1){
        return true;
    }else{
        return false;
    }
}
//入栈
void Push(SqStack &S, int x){
    if(S.top == MaxSize-1){
        cout<<"栈满"<<endl;
        return;
    }
    S.data[++S.top] = x;
}
//出栈
void Pop(SqStack &S, int &x){
    if(S.top == -1){
        cout<<"栈空"<<endl;
        return;
    }
    x = S.data[S.top--];
}
//读栈顶元素
int GetTop(SqStack S){
    if(S.top == -1){
        cout<<"栈空"<<endl;
        return -1;
    }else{
        return S.data[S.top];
    }
}
//遍历栈
void PrintStack(SqStack S){
    while(S.top != -1){
        cout<<S.data[S.top--]<<" ";
    }
    cout<<endl;
}
//销毁栈
void DestroyStack(SqStack &S){
    S.top = -1;
}
int main(){
    SqStack S;
    InitStack(S);
    Push(S,1);//入栈
    Push(S,2);
    Push(S,3);
    Push(S,4);
    cout<<"栈顶元素为:"<<GetTop(S)<<endl;
    cout<<"出栈顺序为:";
    PrintStack(S);
    int x;
    Pop(S,x);
    cout<<x<<"出栈"<<endl;
    cout<<"栈中剩余元素:";
    PrintStack(S);
    Pop(S,x);
    cout<<x<<"出栈"<<endl;
    cout<<"栈中剩余元素:";
    PrintStack(S);
    if(!Empty(S)){
        cout<<"当前栈不为空"<<endl;
    }else{
        cout<<"当前栈为空"<<endl;
    }
    return 0;
}

来自栈——栈的定义及基本操作(初始化、判空、进栈、出栈、遍历栈、销毁栈等)_薛定谔的猫ovo的博客-CSDN博客w


习题


第一题特性,第二题栈顶。


链栈虽然没说,但是通过链表的学习也差不多了。


第三题有点问题,第四题先把值保存在x里,然后改指针域。

目录
相关文章
Visual Studio 2022 中VLD库如何安装
Visual Studio 2022 中VLD库如何安装
802 1
|
XML 开发框架 .NET
|
搜索推荐 架构师 应用服务中间件
Nginx极简入门(三)基于端口的虚拟主机配置
前面讲了如何配置基于IP的虚拟主机,今天讲一讲Nginx如何基于端口的虚拟主机。 需要说明的是:由于本文章是nginx系列文章中的一篇,文章里面很多其他的配置,可能前面的文章已经说讲过,然后后续就没有在介绍,如果出现有些配置没有讲,大家可能需要去看看前面的文章。
Nginx极简入门(三)基于端口的虚拟主机配置
|
4月前
|
XML Java Maven
springboot-多环境配置文件
本文介绍了如何创建开发和生产环境的配置文件,并在IDEA和Maven中进行配置。开发环境中,通过设置profile为`dev`来指定配置文件;生产环境中,使用Maven命令参数`-Pprod`打包并指定配置文件。公共配置可放在`application.yml`中统一管理。日志配置需确保`logback-spring.xml`中的profile正确,以保证日志正常输出。
137 4
springboot-多环境配置文件
|
7月前
|
JSON 数据可视化 测试技术
python+requests接口自动化框架的实现
通过以上步骤,我们构建了一个基本的Python+Requests接口自动化测试框架。这个框架具有良好的扩展性,可以根据实际需求进行功能扩展和优化。它不仅能提高测试效率,还能保证接口的稳定性和可靠性,为软件质量提供有力保障。
311 7
|
9月前
|
存储 关系型数据库 MySQL
深度剖析:MySQL聚合函数 count(expr) 如何工作?如何选择?
本文详细探讨了MySQL中count(expr)函数的不同形式及其执行效率,包括count(*)、count(1)、count(主键)、count(非主键)等。通过对InnoDB和MyISAM引擎的对比分析,解释了它们在不同场景下的实现原理及性能差异。文章还通过实例演示了事务隔离级别对统计结果的影响,并提供了源码分析和总结建议。适合希望深入了解MySQL统计函数的开发者阅读。
132 0
|
11月前
|
资源调度 数据挖掘
R语言回归分析:线性回归模型的构建与评估
【8月更文挑战第31天】线性回归模型是统计分析中一种重要且实用的工具,能够帮助我们理解和预测自变量与因变量之间的线性关系。在R语言中,我们可以轻松地构建和评估线性回归模型,从而对数据背后的关系进行深入的探索和分析。
|
算法 数据库 数据安全/隐私保护
铜锁探密,SM3杂凑算法加强至pro版
铜锁探密,SM3杂凑算法加强至pro版
324 0
|
10月前
|
SQL 人工智能 Serverless
构建一个智能导购助手
通过百炼的Assistant API,您可以构建一个多代理架构的大模型应用,实现智能导购功能。此应用核心为规划助理(Router Agent),根据对话历史和用户输入选择合适助理回复。手机、冰箱、电视导购则根据用户偏好收集参数,智能检索商品并推荐。用户与助理的对话历史为决策提供参考。您可通过函数计算应用模板快速搭建和测试此网站,适用于全天候商品推荐。此架构也可用于智能问诊、求职推荐等场景。
137 1
|
Web App开发 存储 JavaScript
浏览器之性能指标-TTI
浏览器之性能指标-TTI
335 0