数据结构经典算法总复习(上卷)

第一章:数据结构导论

无重要考点,仅需了解时间复杂度。

第二章:线性表

1.获得线性表第i个元素

void GetElem_sq(SqList L, int i, ElemType &e) {
  if (i<1 || i>L.length) ErrorMsg("Invalid i value");
//注意错误监测
  e = L.elem[i-1];//特别注意:C语言数组下标从0开始,与线性表的位序差1
}

2.求两个顺序表的并集

void Union_sq(SqList &La, SqList &Lb) {
  Increment(La, Lb.length);
  for (int i=0; i<Lb.length; ++i) {
    ElemType e = Lb.elem[i];
    int j = 0;
    while(j<La.length && La.elem[j]!=e) ++j;
    if (j==La.length) {
      La.elem[La.length++] = e;
    }
  }
  delete []Lb.elem;
  Lb.length = Lb.listsize = 0;
}

3.求两个单链表的并集

void Union_L(LinkList &La, LinkList &Lb) {
  LNode *pa = La;
  while (Lb) {
    LNode *s = Lb; Lb = Lb->next;//从Lb中依次抽取出s结点
    LNode *p = pa;
    while (p && p->data != s->data) {//与La中结点p依次比对
      p = p->next;
    }
    if (p) delete s;
    else {s->next = La; La = s;}//如果没有,则在La表头添加s
  }
}

4.实现顺序表的就地逆置,即在原表的存储空间将线性表(a1, a2, ..., an−1, an)逆
置为(an, an−1, ..., a2, a1)
void Element_Invert(SqList &L)
{
    int len=L.length;
    Elemtype tmp;
    int i;
    for(i=0;i<len/2;i++)//简单的前后互换
    {
        tmp=L.elem[i];
        L.elem[i]=L.elem[len-i-1];
        L.elem[len-i-1]=tmp;
    }
}

5.循环链表的查找元素

LNode* LocateElem_L3(LinkList L, ElemType e) {
  LNode *p = L->next;
  while (p != L && p->data != e) p = p->next;
  return p == L ? NULL : p;//转了一圈回头了,说明没找到
}

6.双向链表插入元素

void ListInsert_DL(DLinkList &L, DLNode *p, DLNode *s) {//s插入到链表中p的前面
  s->prior = p->prior;
  s->next = p;//先把s插好
  p->prior->next = s;
  p->prior = s;//再去动p结点
}

已知线性表用顺序存储结构表示,表中数据元素为 n 个正整数,试写一个算法,分离该表中的奇数和偶数,使得所有奇数集中放在左侧,偶数集中放在右侧,要求不借用辅助数组且时间复杂度为O(n)

7.第一个顺序表实现,较为简单

void Element_EvenOdd(SqList &L)//哨兵思想,左右相合,有点快速排序那味了
{
    int left=0,right=L.length -1,tmp;
    while(left<right)
    {
        while(L.elem[left]%2==1) //为 奇 数
        {
            left++;
        }
        while(L.elem[right]%2==0) //为 偶 数
        {
            right --;
        }
        tmp=L.elem[left];
        L.elem[left]=L.elem[right];
        L.elem[right]=tmp;
    }
}

8.第二个链表实现,如果存在头指针,则无需考虑第一个插入的特殊情况。

void oddEvenList(Linklist& L) {//没有头指针的情况
    if (!L ||!L->next) return;
    LNode *oddHead=NULL;
    LNode *oddTail=NULL;
    LNode *evenHead=NULL;
    LNode *evenTail=NULL;
    LNode *curr=L;
    while (curr) {
        if (curr->val % 2 == 1) {
            if (!oddHead) {//此时需要考虑第一个奇的情况
                oddHead=curr;
                oddTail=curr;
            } else {
                oddTail ->next=curr;
                oddTail=oddTail ->next;//更新odd链表的尾指针
            }
        } else {
            if (!evenHead) {//需要考虑第一个偶的情况
                evenHead=curr;
                evenTail=curr;
            } else {
                evenTail ->next=curr;
                evenTail=evenTail ->next;//更新even链表的尾指针
            }
        }
        curr=curr->next;
    }
    if (oddHead) {
        oddTail ->next=evenHead;//存在奇数的话,奇数表尾连接偶数表头
            if (evenTail) {
                evenTail ->next=NULL;//如果存在偶数的话,偶数表尾置空;如果不存在,本身就是空表尾
            }
        L=oddHead;
    } else {
        L=evenHead;//如果不存在奇数,则链表头为even链表的表头
    }
}

第三章:栈和队列

1.判断以为结束符的字符序列是否为形如”xyz@zyx” 模式的逆序字符序列
bool judgechar(Sqstack &s,char *p) {
    char e;
    while(*p!='@'&& *p!='#'){//将@前内容入栈
        push(s,*p);
        p++;
    }
    if(*p=='#') return FALSE;//若没有@则报False
    p++;
    while(*p!='#'){
        if(pop(s,e)&&e==*p) p++;//依次比较且出栈,即@前的和@后的依次抵消
        else return FALSE;
    }
    if(Stackempty(s)) return TRUE;//都抵消了,则对了
    else return FALSE;
}

2.数制转换问题,从N进制转为d进制。

void conversion(int N, int d) {
  if (N<=0 || d<=0) ErrorMsg("Input error");
  Stack S; InitStack(S);
  while (N) { Push(S, N%d); N = N/d; }//先除的余数,先入栈
  int e;
  while (Pop(S, e)) { cout << e; }//后出栈
  cout << endl;
}

3.设中缀表达式由单字母变量,双目运算符和圆括号组成,试写一个算法,将一个书写正确的中缀表达式转为后缀表达式。
void getsuffix(char exp[],char suffix[]) {
    SqStack S;
    InitStack_sq(S,10);//随手输一个10
    Push_sq(S,'#');//开头的符号
    char *p=exp;
    char c,ch;
    int k=0;
    while(!StackEmpty(S){
        ch=p++;
        if(!isoperator(ch)){//判断是否为符号
            suffix[k++]=ch;//不为符号,直接写入表达式
            continue;
        }
        switch(ch){//若为符号
            case '(':Push_sq(S,ch);break;
            case ')'://若为反括号,则一直取出,直到出现正括号
                while(Pop_sq(S,c)&&c!='(') suffix[k++]=c;
                break;
            default:
                while(GetTop_sq(S,c) && preop(c,ch)) 
//判断c(前)和ch(后)优先级,c>=ch则为true
                    {suffix[k++]=c;Pop_sq(S,c);}
                if(ch!='#') push(S,ch);
                break;
        }
    }
    suffix[k]='\0';
    DestoryStack_sq(S);
}

4.求顺序队列的长度

int QueueLength_sq(SqQueue Q) {
//当Q.rear=Q.front时为空队列
//当Q.front-Q.rear=1时为满队列
  return (Q.rear - Q.front + Q.queuesize) % Q.queuesize;
}

5.顺序队列的入队和出队

void EnQueue_sq(SqQueue &Q, ElemType e) {
  if ((Q.rear+1) % Q.queuesize == Q.front) Increment(Q);//已为满
  Q.elem[Q.rear] = e; Q.rear = (Q.rear+1) % Q.queuesize;
}

bool DeQueue_sq(SqQueue &Q, ElemType &e) {
  if (Q.front == Q.rear) return false;//已为空
  e = Q.elem[Q.front]; Q.front = (Q.front+1) % Q.queuesize;
  return true;
}

6.汉诺塔问题

void hanoi(int n, char x, char y, char z) {
  if (n==1) move(x,1,z);//跳出递归条件,即最简问题,将1个盘子由X移到Z
  else {
    hanoi(n-1, x, z, y);//将n-1个盘子由X移到Y
    move(x,n,z);//将盘子n由X移到Z
    hanoi(n-1, y, x, z);//将n-1个盘子由Y移到Z
  }
}

void move(char u, int i, char v) {
  printf("move %d from %c to %c", i, u, v);
}

7.八皇后问题

#define N 8 //8*8的国际象棋棋盘
int X[N];
int B[2*N-1],C[2*N-1];
int A[N];
void mark(int i,int j,int flag) {//标志横线,左斜线,右斜线能否再次放置
	A[j]=B[i+j]=C[i-j+7]=flag;
}
bool AbleSet(int i,int j) {//判断这个横线,左斜线,右斜线能否放置
	return (A[i]==0&&B[i+j]==0&&C[i-j+7]==0);
}
void eightQueen(int k) {//从第0列开始尝试,一直到N-1
	for (int i = 0; i < N; i++) {
		if(AbleSet(k,i)) {
			X[k]=i;
			mark(k,i,1);
			if(k==N-1){for (k=0;k<N;k++)cout << X[k] << endl;}
			else eightQueen(k+1);//如果暂时合适,则进入下一列开始尝试
			mark(k,i,0);//没有合适情况,则回溯,取消这里的放置,重新尝试另一种
		}
	}//若运行到这里,则说明这一列已经放不了皇后了,前面的列有些问题,该工作栈弹出,回溯上一级。
}

8.写一个递归算法,对不带头结点的单链表进行逆序,要求输入参数是单链表的头指针,返回逆序之后的头指针。

Link_node inverse(Link_node ∗head){
    Link_node ∗new_head;
    if(head−>next == NULL) return head;//最简单情况,递归终止条件
    else{//将长度为n的链表拆分为1+(n-1)两部分,对后面部分进行逆序,再将这两部分交换位置即可
        new_head = inverse(head−>next);
        head−>next−>next = head;
        head−>next = NULL;
        return new_head;
    }
}

第四章:数组

1.快速转置稀疏矩阵,要求时间复杂度等于nu+tu(列+非零元个数)

ps:普通的行列转换要两个for,时间复杂度为nu*mu(行*列),远大于快速转置。

void FastTranspose(TSMatrix M, TSMatrix &T) {//M矩阵转置为T
  int p, q, col;
  T.mu = M.nu; T.nu = M.mu; T.tu = M.tu;//mu、nu、tu代表矩阵行、列、非零元个数,构造T矩阵
  if (T.tu) {
    T.data = new Triple[T.tu]; rpos = new int[T.mu];
    int *num = new int[M.nu];
    for (col=0; col<M.nu; ++col) num[col] = 0;
//初始化num数组,num存储矩阵M的col列的非零元个数
    for (p=0; p<M.tu; ++p) ++num[M.data[p].j];
//num数组的下标表示M的第p个元素的列(j),制造num完成
    rpos[0] = 0;                //rpos数组代表M中转置后元素应插入位置
    for (col=1; col<M.nu; ++col) rpos[col] = rpos[col-1] + num[col-1];
//制造rpos数组,非首项则按此规律计算在T中位置
    for (p=0; p<M.tu; ++p) {
      col = M.data[p].j; q=rpos[col];//找原M的列,和应该插入T中该列值的位置
      T.data[q].i = M.data[p].j; T.data[q].j = M.data[p].i;
      T.data[q].e = M.data[p].e; ++rpos[col];//转置操作,俩矩阵行(i)与列(j)互换,操作数不变,次序同时递加。
    }
  }
  else {//如果没有非零元
    T.data = NULL; rpos = NULL;
  }
}

理解示意图如下:

由【0 1 12】的“1”(列),找到rpos中的col=1,次序值为2,则插入到T中第二个位置(从上到下数第三个),转置后即【1 0 12】。

其他同理。


这一节就差不多,一篇文章无需很长,在这里留个空,下篇文章明天。

重头戏名单:树,图,查找表,排序

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Windows11 安装 Ubuntu-20.04,同时安装配置 zsh shell,配置 git 别名(alias),大大提高开发效率

背景&#xff1a;家里配置了一台 Windows 电脑&#xff0c;有时候需要用到 vscode 开发测试一些代码&#xff0c;在使用过程中发现原生 windows 敲代码不是很友好&#xff0c;于是想到配置 wsl&#xff0c;安装 Ubuntu&#xff0c;并安装配置 zsh shell&#xff0c;同时配置 gi…

PE文件结构

PE文件是Windows系统下可执行文件的总称&#xff0c;英文全称 Portable Executable 可移植的可执行文件&#xff0c;常见的有exe、dll、sys、com、ocx 对于学习反&#xff08;木马、免杀、病毒、外挂、内核&#xff09;&#xff0c;了解PE文件结构是非常有必要且非常非常重要的…

Helm 官方脚本

Helm 官方脚本 #!/usr/bin/env bash# Copyright The Helm Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # …

JSON 系列之1:将 JSON 数据存储在 Oracle 数据库中

本文为Oracle数据库JSON学习系列的第一篇&#xff0c;讲述如何将JSON文档存储到数据库中&#xff0c;包括了版本为19c和23ai的情形。 19c中的JSON 先来看一下数据库版本为19c时的情形。 创建表colortab&#xff0c;其中color列的长度设为4000。若color的长度需要设为32767&a…

C语言-结构体内存大小

#include <stdio.h> #include <string.h> struct S1 { char a;//1 int b;//4 char c;//1 }; //分析 默认对齐数 成员对齐数 对齐数(前两个最小值) 最大对齐数 // 8 1 …

PyTorch 神经网络回归(Regression)任务:关系拟合与优化过程

PyTorch 神经网络回归&#xff08;Regression&#xff09;任务&#xff1a;关系拟合与优化过程 本教程介绍了如何使用 PyTorch 构建一个简单的神经网络来实现关系拟合&#xff0c;具体演示了从数据准备到模型训练和可视化的完整过程。首先&#xff0c;利用一维线性空间生成带噪…

渐开线齿轮和摆线齿轮有什么区别?

摆线齿形与渐开线齿形的区别 虽然在比对这两种齿形&#xff0c;但有一个事情希望大家注意&#xff1a;渐开线齿轮只是摆线齿轮的一个特例。 &#xff08;1&#xff09;摆线齿形的压力角在啮合开始时最大&#xff0c;在齿节点减小到零&#xff0c;在啮合结束时再次增大到最大…

Debian 12 安装配置 fail2ban 保护 SSH 访问

背景介绍 双十一的时候薅羊毛租了台腾讯云的虚机, 是真便宜, 只是没想到才跑了一个月, 系统里面就收集到了巨多的 SSH 恶意登录失败记录. 只能说, 互联网真的是太不安全了. 之前有用过 fail2ban 在 CentOS 7 上面做过防护, 不过那已经是好久好久之前的故事了, 好多方法已经不…

Vulhub靶场Apache解析漏洞

一.apache_parsing 原理&#xff1a;Apache HTTPD ⽀持⼀个⽂件拥有多个后缀&#xff0c;并为不同后缀执⾏不同的指令。在Apache1.x/2.x中Apache 解析⽂件的规则是从右到左开始判断解析,如果后缀名为不可识别⽂件解析,就再往左判断。如 1.php.xxxxx 打开靶场 创建一个名为1.p…

MATLAB 抛物线拟合(Quadratic,二维)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 这里仍然是最小二乘法的应用,其推导过程如下所述: 1.二次函数模型: 其中,a、b 和 c 是需要确定的参数。 2.最小二乘法 假设我们有一组数据点 ( x 1 ​ , y 1

重温设计模式--原型模式

文章目录 原型模式定义原型模式UML图优点缺点使用场景C 代码示例深拷贝、浅拷贝 原型模式定义 用原型实例指定创建对象的种类&#xff0c;并且通过拷贝这些原型创建新的对象&#xff1b; 核心中的核心就是 克隆clone ,后面讲 原型模式是一种创建型设计模式&#xff0c;它的主要…

mac iterm2 使用 lrzsz

前言 mac os 终端不支持使用 rz sz 上传下载文件&#xff0c;本文提供解决方法。 mac 上安装 brew install lrzsz两个脚本 注意&#xff1a;/usr/local/bin/iterm2-send-zmodem.sh 中的 sz命令路径要和你mac 上 sz 命令路径一致。 /usr/local/bin/iterm2-recv-zmodem.sh 中…

【基础篇】1. JasperSoft Studio编辑器与报表属性介绍

编辑器介绍 Jaspersoft Studio有一个多选项卡编辑器&#xff0c;其中包括三个标签&#xff1a;设计&#xff0c;源代码和预览。 Design&#xff1a;报表设计页面&#xff0c;可以图形化拖拉组件设计报表&#xff0c;打开报表文件的主页面Source&#xff1a;源代码页码&#xff…

【magic-dash】01:magic-dash创建单页面应用及二次开发

文章目录 一、magic-dash是什么1.1 安装1.2 使用1.2.1 查看内置项目模板1.2.2 生成指定项目模板1.2.3 查看当前magic-dash版本1.2.4 查看命令说明1.2.5 内置模板列表二、创建虚拟环境并安装magic-dash三、magic-dash单页工具应用开发3.1 创建单页面项目3.1.1 使用命令行创建单页…

《Pytorch框架CV开发-从入门到实战》

目录 1.环境部署2.自动梯度计算张量 tensor3.线性回归4.逻辑回归6.人工神经网络的基本概念6.1 感知器6.2 激活函数6.3多层感知器6.4 反向传播算法——前向传播6.5 反向传播算法——反向传播6.6 反向传播算法——训练方法7.Pytorch基础数据集8.手写数字识别人工神经网络训练8.1 …

WebRTC学习二:WebRTC音视频数据采集

系列文章目录 第一篇 基于SRS 的 WebRTC 环境搭建 第二篇 基于SRS 实现RTSP接入与WebRTC播放 第三篇 centos下基于ZLMediaKit 的WebRTC 环境搭建 第四篇 WebRTC 学习一&#xff1a;获取音频和视频设备 第五篇 WebRTC学习二&#xff1a;WebRTC音视频数据采集 文章目录 系列文章…

国自然联合项目|影像组学智能分析理论与关键技术|基金申请·24-12-25

小罗碎碎念 该项目为国自然联合基金项目&#xff0c;执行年限为2019年1月至2022年12月&#xff0c;直接费用为204万元。 项目研究内容包括影像组学分析、智能计算、医疗风险评估等&#xff0c;旨在通过模拟医生诊断过程&#xff0c;推动人工智能在医疗领域的创新。 项目取得了…

怎样配备公共配套设施,才能让啤酒酿造流程高效环保?

今天&#xff0c;天泰邀请大家和我一起走进啤酒厂&#xff0c;了解水、蒸汽、压缩空气和二氧化碳这些基础设施如何助力啤酒生产&#xff0c;实现高效与环保的完美结合。 水 水是啤酒酿造的基础&#xff0c;啤酒厂对水质的要求极高。为了确保水质达标&#xff0c;啤酒厂设有专…

医疗行业 UI 设计系列合集(一):精准定位

在当今数字化时代&#xff0c;医疗行业与信息技术的融合日益紧密&#xff0c;UI 设计在其中扮演着至关重要的角色。精准定位的 UI 设计能够显著提升医疗产品与服务的用户体验&#xff0c;进而对医疗效果和患者满意度产生积极影响。 一、医疗行业 UI 设计的重要性概述 医疗行业…

本科阶段最后一次竞赛Vlog——2024年智能车大赛智慧医疗组准备全过程——12使用YOLO-Bin

本科阶段最后一次竞赛Vlog——2024年智能车大赛智慧医疗组准备全过程——12使用YOLO-Bin ​ 根据前面内容&#xff0c;所有的子任务已经基本结束&#xff0c;接下来就是调用转化的bin模型进行最后的逻辑控制了 1 .YOLO的bin使用 ​ 对于yolo其实有个简单的办法&#xff0c;也…