当前位置: 首页 > news >正文

C语言:3.31

一、链表真题:2019年42题

解析:任何408真题但凡涉及链表的一定都会需要定义一个头节点,很容易被“初始时队列为空”这个条件迷惑,实际上只有一个头节点也是为空。

上面这个有关“头节点”的理解也没错,但这道题的关键在于:被视为“头节点”的那个节点是在变化的,而非静止不动的那一个头节点,可以类比“顺序表的循环队列”也需要一个空位来标志着队满。

事实上:将顺序表的直接类比过来就行了。

整体代码:

//首先定义链表节点
typedef struct LinkNode
{
	int val;
	LinkNode* next;
}LinkNode;


//链表结构体
typedef struct
{
	LinkNode* front;
	LinkNode* rear;
}QueueList;

QueueList Q;


//初始化链表
void InitQ(QueueList &Q)
{
	LinkNode* q = new LinkNode();
	q->next = q;
	Q.front = Q.rear = q;
}

//入队
bool Push(QueueList &Q,int x)
{
	if (Q.rear->next == Q.front)
	{
		LinkNode* q = new LinkNode();
		Q.rear->val = x;
		Q.rear->next = q;
		Q.rear = q;
		q->next = Q.front;
	}
	Q.rear->val = x;
	Q.rear = Q.rear->next;
	return true;
}

//出队
bool Pop(QueueList &Q, int &x)
{
	if (Q.front == Q.rear) return false;
	x = Q.front->val;
	Q.front = Q.front->next;
}

二、13.4:树与二叉树原理解析

1、二叉树层次建树,必须用到“辅助队列”

忍不住了,所以放弃这个层次建树,转向“前序遍历建树”:一步一步写数据结构(二叉树的建立和遍历,c++) - Jymoon - 博客园

发现更垃圾了。

2、二叉树的前序、中序、后序遍历

简单

3、二叉树的层序遍历

使用辅助队列,先将根节点入队,开启循环,循环条件:队列是否为空,队列出队,判断左节点是否为空,若不为空则入队;判断右节点是否为空,不为空则入队。

4、真题:2014年41题

还是比较基础的题目

#include<iostream>
#include"function.h"
using namespace std;

void CreateTree(BTree& T)
{
	int x;
	cin >> x;
	if (x != 0)
	{
		BTree p = new BNode(x);
		T = p;
		CreateTree(p->left);
		CreateTree(p->right);
	}
}

int WPL(BTree T,int x)
{
	if (T->left == NULL && T->right == NULL)
	{
		return T->data * x;
	}
	else
	{
		int l = WPL(T->left, x + 1);
		int r = WPL(T->right, x + 1);
		return l + r;
	}
}

//二叉树前序遍历建树
int main()
{

	//树根
	BTree tree=NULL;
	CreateTree(tree);
	cout << WPL(tree,0) << endl;
}

三、01基础课:栈与队列

1、卡特兰数

2、共享栈

节省存储空间又降低了上溢的风险,解释如下:

不需要判断是否为头节点,因为不带头节点的链表栈顶会初始化为NULL;

3、循环队列

(1)依旧是线性的逻辑结构,通过“取模”操作使其成为一个环;

(2)若不采用别的手段,则队满和队空的判断条件都会是:rear=front

手段一:加一个空位(很熟悉了)

手段二:增设结构成员size,表示队列中到底多少数量的元素。

手段三:增设标志位tag

每次入队操作都将tag位置为1,表示:上一次做的操作是入队;

每次出队操作将tag为置为0,表示:上一次做的操作是出队;

若rear=front,且tag=1,表示:上一步入队导致的两个指针相等,则队列满;否则队列空。

4、带头节点的链式队列

front永远指向头节点;

注意:链队出队时要考虑是否是最后一个节点,如果是的话,同时要修改尾指针。

带头节点判断队空:rear=front

不带头节点判断队空:rear=NULL,front=NULL

而不带头节点的链栈这俩相等是插入一个节点后,并非队空。

四、栈和队列的应用

1、括号匹配(leetcode原题)

class Solution {
public:
    bool isValid(string s) {
     stack<char>my;
     int len=s.size();
     for(int i=0;i<len;i++)
     {
        if(s[i]=='('||s[i]=='{'||s[i]=='[') my.push(s[i]);
        else if(s[i]==')')
        {
            if(my.empty()) return false;
            char x=my.top();
            if(x!='(')  return false;
            my.pop();
        }
        else if(s[i]==']')
        {
            if(my.empty()) return false;
            char y=my.top();
            if(y!='[')  return false;
             my.pop();
        }
        else
        {
            if(s[i]=='}'||my.empty())
            {
                if(my.empty()) return false;
                char z=my.top();
                if(z!='{') return false;
                 my.pop();
            }
        }
     }
     
     if(my.empty())
     {
        return true;
     }
     else{
        return false;
     }
    }
};

使用栈,若是"([{",则直接入栈;若是")]}",则出栈判断栈顶元素是否为与其匹配的括号。

若是,则继续走下去;若不是,则直接返回false;若遇到右括号且当前栈为空,则直接返回false

2、中缀表达式转后缀表达式

后缀表达式又称为“逆波兰表达式”,后缀表达式是计算机认识的式子。

需要两个栈,一个结果栈,一个temp栈:

(1)若遇到运算符,则直接入结果栈;

(2)遇到操作符,操作符若为(,则直接入temp栈;

若为),将temp栈内的操作符依次出栈入结果栈,直到遇到(符号;

若为普通操作符,则判断temp栈顶元素与当前操作符的优先级,若大于等于栈顶操作符,则依次出栈直至小于;

若小于则当前操作符入temp栈。

最后结果栈内从栈底到栈顶的顺序就是结果。

注:左小括号“(”的优先级对于temp栈内元素最高,但对于temp栈外元素最低。

3、后缀表达式求值

需要一个存储操作数的栈op,遇见操作数时就将其入栈,遇见操作符时,就从栈顶出栈两个操作数,先出栈的是右操作数,随后将计算结果再次存入栈中。

最后栈低的元素就是最终结果。

4、中缀表达式求值

把2与3两个过程结合起来,依旧是两个栈,一个temp栈存放操作符,一个结果栈存放操作数,当temp内弹出操作符时,按照3的过程从结果栈中弹出操作数,运算后再次将本次结果放入结果栈中。

五、数组

1、二维数组

记住从(0,0)开始数的行优先:

 其实仔细看一下以(0,0)开始的下标(i,j)的含义:就是前面有i行j列

若以(1,1)开始,则减1就好了。

六、特殊矩阵

1、对称矩阵

注意:数组一般下标从0开始,矩阵的下标一般从1开始。

求的是元素在数组中的下标。

注意:若存储的是下三角区和主对角线,那么求上三角区 Aij在数组中的位置要转化为下三角。

2、三角矩阵:某半区全为常数k

多存一个k好了,前面有几个元素其在数组内的下标就是几。

3、三对角矩阵,带状矩阵

(1)定义:除了主对角线以及上面、下面的对角线以外,其余元素全为0。

(2)确认位置:关键在于怎么确定Aij在本行是第几个元素:

Aii在本行是第2个元素,所以:j-i+2

(3)反着来

告诉你Aij在一维数组中的下标是k,那么i、j、k的关系是什么?

知道一维数组的下标k,可以推出是在矩阵中的本行的第几个元素。

4、稀疏矩阵

三元组:行号+列号+值

能通过只看右边的三元组从而还原整个稀疏矩阵么,答案是否定的。

因为并不知道原来的稀疏矩阵共有几行几列。

所以:还需要两个变量分别存行数与列数。

七、字符串匹配

1、暴力匹配

时间复杂度:O(n²)

2、KMP算法

(1)三个基本定义

前缀:不包括串中最后一个字符的所有前缀

后缀:不包括串中第一个字符的所有后缀

PM:最长的相同缀的长度,而非数量。

(2)机械的求next数组

求出每个子串的部分匹配值;将其右移;首位补-1

(3)求nextval数组

i是否等于next[i],若相等则修改next[i]=next[next[i]];

因为之所以要用next数组,一定是发生了失配,则i不等于j,若next[i]=i,那么j也一定失配;

所以要修改。

注意:势必从前往后修改

八、顺序查找及原理

1、2009年真题

不管是寻找链表中的哪一个具体位置的节点,都可以使用“双指针法”

代码如下:

#include<iostream>
using namespace std;


//首先定义链表节点
typedef struct LinkNode
{
	int data;
	LinkNode* next;
}LinkNode,*LinkList;



//初始化
void InitLinkList(LinkList &L)
{
	L = new LinkNode();
	L->next = NULL;

}

//尾插法建立链表
void Insert(LinkList& L)
{
	//定义一个尾指针
	LinkNode* rear = L;
	int x;
	while (cin >> x && x != 0)
	{
		LinkNode* p = new LinkNode();
		p->data = x;
		p->next = NULL;
		rear->next = p;
		rear = p;
	}
}

int K(LinkList L, int k)
{
	LinkNode* pre = L;
	LinkNode* post = L;

	while (k--)
	{
		pre = pre->next;
		if (!pre) return 0;
	}
	while (pre)
	{
		pre = pre->next;
		post = post->next;
	}
	cout << post->data << endl;
	return 1;
}



int main()
{
	//声明一个链表头节点
	LinkList L;

	//初始化链表头节点
	InitLinkList(L);
	Insert(L);
	int y = K(L, 5);
}

2、顺序查找代码

#include<iostream>
using namespace std;

//之前的顺序表用静态数组实现,现在用堆实现
typedef struct
{
	int* T;
	int len;
}STable;

void Init(STable& S, int len)
{
	//多申请了一个位置作为哨兵
	S.len = len + 1;
	S.T = new int[S.len];
	for (int i = 0; i < S.len; i++)
	{
		S.T[i] = i;
	}
}

//进行查找过程
int Search(STable& S, int x)
{
	for (int j = S.len - 1; j > 0; j--)
	{
		if (x == S.T[j]) return j;
	}
	return 0;
}

int main()
{
	STable s;
	Init(s, 10);
	int y = Search(s, 5);
	cout << y << endl;
}

九、折半查找实战

折半查找又称“二分查找”,仅适用于有序的顺序表;

(1)对数组进行排序

与c++内容器排序一样,都需要给出数组的起始地址与终止地址,所以是:

	//对数组进行排序
	sort(s.T, s.T+s.len);

(2)整体代码

#include<iostream>
#include<algorithm>
using namespace std;

//之前的顺序表用静态数组实现,现在用堆实现
typedef struct
{
	int* T;
	int len;
}STable;

void Init(STable& S, int len)
{
	//多申请了一个位置作为哨兵
	S.len = len + 1;
	S.T = new int[S.len];
	for (int i = 0; i < S.len; i++)
	{
		S.T[i] = i;
	}
}

int Search(STable S, int x)
{
	int low = 0, high = S.len - 1;
	while (low <= high)
	{
		int mid = (low + high) / 2;
		if (S.T[mid] == x) return mid;
		else if (S.T[mid] > x)
		{
			high = mid - 1;
		}
		else low = mid + 1;
	}
	return -1;
}

int main()
{
	STable s;
	Init(s, 10);

	//对数组进行排序
	sort(s.T, s.T+s.len);

	//折半查找
	int y = Search(s, 555);
	cout << y << endl;
}

http://www.dtcms.com/a/112059.html

相关文章:

  • 【YOLO系列(V5-V12)通用数据集-火灾烟雾检测数据集】
  • 大模型学习四:‌DeepSeek Janus-Pro 多模态理解和生成模型 本地部署指南(折腾版)
  • 七均线策略思路
  • Mac VM 卸载 win10 安装win7系统
  • Win7下安装高版本node.js 16.3.0 以及webpack插件的构建
  • Apache Camel指南-第四章:路由径构建之异常处理
  • 如何使用 IntelliJ IDEA 开发命令行程序(或 Swing 程序)并手动管理依赖(不使用 pom.xml)
  • 从飞机的状态矩阵A阵求运动模态的特征根、求传递函数矩阵
  • NOIP2013提高组.华容道
  • 从菜鸟到高手的提示词优化指南‌
  • Muduo网络库介绍
  • Sensodrive力控关节模组SensoJoint:TÜV安全认证助力机器人开发
  • 主机和虚拟机间的网络通信
  • LeetCode算法题(Go语言实现)_29
  • JavaScript重难点突破:事件循环
  • 基于 Python 的自然语言处理系列(70):检索增强生成(RAG)
  • Go语言-初学者日记(八):构建、部署与 Docker 化
  • 《操作系统真象还原》第五章(2)——启用内存分页机制
  • 蓝桥杯15届 宝石组合
  • 【HC-05蓝牙模块】基础AT指令测试
  • 思维链 Chain-of-Thought(COT)
  • 视野,,地面覆盖,重叠需求,FPS,飞行速度等的计算公式
  • LLM面试题五
  • JVM 有哪些垃圾回收器
  • 【2023】ORIGIN或MATLAB 颜色图,等高图,颜色条——需要拟合补全中间的颜色
  • 算法--最长上升子序列
  • 京东零售首次公开!6B参数时序大模型实现20000款商品自动补货预测
  • Java 搭建 MC 1.18.2 Forge 开发环境
  • 《探索边缘计算:重塑未来智能物联网的关键技术》
  • agent 入门