数据结构PTA全八章个人复现wp

数据结构PTA全八章个人复现wp

纯个人wp,轻点骂,骂就是骂得对QWQ

第一章

在这里插入图片描述线性结构:元素间一对一
非线性结构:集合,树(存在有2个以上前后驱的结点),图
在这里插入图片描述在这里插入图片描述数据元素:数据的基本单位
数据项:数据最小单位
数据结构:带有结构的各种数据元素的集合
在这里插入图片描述逻辑结构是理论上的东西,是虚拟的
在这里插入图片描述在这里插入图片描述在此简单循环中x(n)和自增变量y的1/2在同一数量级
在这里插入图片描述

第二章

在这里插入图片描述
做完上述所有操作后p指向了hb的最后一个结点,此时只需连到ha的头上即可,然后返回题目要求的头指针ha
在这里插入图片描述存储密度:结点数据所占空间/结点占的空间
顺序表=1
链表<1(还有指针域)
在这里插入图片描述单链表先插后断(先断就会找不到next结点)
在这里插入图片描述s连到目标结点,目标结点的尾结点连回s,p断链并连到s,s的尾指针连回p
在这里插入图片描述用q指向想删的结点,完成头结点接到第三个结点,此时需注意pq是否指向同一个结点,若是则要更新尾指针p使其指向头结点
在这里插入图片描述因为是顺序存储,所以按数组想就行,直接可访问结点,增加结点需一个简单循环
在这里插入图片描述同上一题
在这里插入图片描述注意本题说的是在最后插入和删除,所以顺序表也能以O(1)完成
在这里插入图片描述在这里插入图片描述C:遍历肯定是一个N的循环,求第i个结点要循环i次,取最坏是n,所以也是O(N)
AD:知道单链表结点的地址就像数组知道下标一样,所以是O(1)
在这里插入图片描述查找最后一个结点,最节省时间的肯定是知道头结点的双循环链表,因为可以通过头结点的前指针直接访问尾结点
在这里插入图片描述两个要求:O(1)和空间最小
空间小:不用双链表
同时O(1):必须是知道尾指针的循环链表
在这里插入图片描述在这里插入图片描述查找已知数据域的结点显然是O(1)
在这里插入图片描述
在这里插入图片描述t连上去,头结点改变,更新头结点
在这里插入图片描述在这里插入图片描述s的尾指针连回p,s连到目标结点(p的下一个结点),由p访问到目标结点并使它连回s,最后把p连到s

在这里插入图片描述(buhui)

第三章

在这里插入图片描述连续进栈,且先进后出

在这里插入图片描述顺序栈是一种基于数组的数据结构,其实现方式是利用一个一维数组存储栈中的元素,同时使用一个变量top来指示栈顶元素在数组中的位置。当进行进栈和出栈操作时,只需要改变top的值即可。
因此,对于大小为m的顺序栈而言,进栈和出栈操作都不应受到操作次数的限制,选F

在这里插入图片描述在这里插入图片描述经典节约空间的操作,两个栈头对头,即栈底分别在两端
在这里插入图片描述顺序结构下
在这里插入图片描述除非1第一个出栈,不然1不可能在2的前面出栈
在这里插入图片描述链式存储是动态申请内存
在这里插入图片描述栈只能在栈顶进行
在这里插入图片描述在这里插入图片描述通常使用堆栈来处理…
在这里插入图片描述循环队列和普通队列相比,它的主要优势之一就是在执行出队操作时可以避免大量元素的移动。这是因为进行出队操作时,只需要将队头指针front往后移一位,就可以删除队头元素
在这里插入图片描述在这里插入图片描述(rear - front + n) % n,其中n为环形队列的容量
在这里插入图片描述反了,在队尾插入,队头删除(因为先进先出)

在这里插入图片描述选F,(buhui)以下来自gpt的胡编:

该命题未必成立。
当删除 L 中某个物品后,可能会出现两种情况:一是 FF(L’) 等于 FF(L); 二是 FF(L’) 小于 FF(L)。如果 FF(L’) 等于 FF(L),则显然 FF(L’) 至多是 FF(L)。如果 FF(L’) 小于 FF(L),那么问题就来了。因为L’ 是从 L 中删除一个物品得到的,根据贪心算法中子问题最优解推出原问题最优解的思路,FF(L′) 的结果可能比删除前少一个箱子,也可能相同或多一个箱子。具体例子可能如下:
假设L为 [0.7, 0.5, 0.6, 0.4],用 First Fit 算法装箱需要的箱子数为 2(第一个箱子装 0.7 和 0.4,第二个箱子装 0.5 和 0.6)。如果从 L 中删除 0.7 这个物品,得到 L’ = [0.5, 0.6, 0.4],同样用 First Fit 算法装箱,则需要的箱子数仍然是 2(第一个箱子装 0.5 和 0.4,第二个箱子装 0.6)。因此,在这个例子中 FF(L’) 等于 FF(L),意味着 FF(L’) 至多是FF(L)。
但是,如果我们将L修改为L=[0.9, 0.5, 0.8, 0.7, 0.4],用 First Fit 算法装箱,则需要的箱子数为 3(第一个箱子装 0.9 和 0.1,第二个箱子只能装 0.5,第三个箱子装 0.8 和 0.7)。如果从 L 中删除任意一个物品后得到 L’,再用 First Fit 算法装箱,可能会有不同结果,例如:
如果删除 0.9 得到 L’=[0.5, 0.8, 0.7, 0.4],则需要 3 个箱子;
如果删除 0.5 得到 L’=[0.9, 0.8, 0.7, 0.4],则需要 4 个箱子;
如果删除 0.8 得到 L’=[0.9, 0.5, 0.7, 0.4],则需要 3 个箱子。
因此,在这个例子中,FF(L’) 不一定等于 FF(L),也可能大于FF(L)。所以我们无法肯定地说“FF(L′) 至多是 FF(L)”。
总之,具体情况具体分析,对于不同的 L 和 L’,它们与它们对应的 FF 值之间的大小关系不能一概而论,需要具体问题具体分析。

在这里插入图片描述少用一个存储空间的方法是为了解决无法判别队列满还是空。

在这里插入图片描述
在这里插入图片描述疑似选A,以下为好兄弟gpt的解释:

正确答案是A。在递归调用过程中,系统会为每一层递归调用创建一个栈帧,用于存储该层调用时需要保存的信息,例如返回地址、函数参数、局部变量等,在递归返回时将这些信息从栈帧中弹出,实现递归的回溯。
选项B是错误的,因为递归的调用顺序是按照先入后出的顺序进行的。
选项C也是错误的,因为递归的调用过程中,栈会一直处于被占用的状态,直到递归结束才可以释放,而不是在某个时刻就不再需要使用栈了。
选项D也是错误的,因为递归函数的调用次数并不完全取决于对应工作栈的元素个数,而是由程序控制流程和递归调用条件所限制。

在这里插入图片描述在队尾插,先插,后更新尾指针
在这里插入图片描述循环队列中队尾指针指向最后一个元素的下一个位置,队头指针指向第一个元素
在这里插入图片描述需要注意的是,这是个队列,它的头是在尾的“后面”(以顺时针来说,因为头是删除元素的)
所以队满就是头被r+1在循环的意义上追上,即f=(r+1)%n
在这里插入图片描述以特例刚初始化时(r=f=0)记,即r==f
在这里插入图片描述删除:(f+1)%n
增加:(r+1)%n
n为总空间数
在这里插入图片描述同上题
在这里插入图片描述
在这里插入图片描述首先明白一点,线性队列的假溢出指的是队列中还有空闲空间却无法继续插入元素的情况,而(少用一个存储元素的)循环队列可以解决这个问题,让它可以继续插入元素。
所以引入循环队列的本质目的是为了克服假溢出,而非更好的利用空间,虽然它不可否认的使我们可以更好的利用空间,但这只是副作用。

另外:循环队列有无法判断队满的问题,而少用一个存储元素就是在解决这个问题。
具体:尾指针的next是头指针时,明明还空着一个位子却插不了元素(因为此时r+1=f,误判为了队满),而加个空位置可以起到“缓冲的作用”,从而解决该问题

在这里插入图片描述

第四章(水)

在这里插入图片描述
广义表的每个元素可以是原子也可以是另一个广义表,所以说它是递归的
在这里插入图片描述稀疏矩阵不能用顺序结构存储且不递归
在这里插入图片描述LOC(i,j)=LOC(1,1)+[n*(i-1)+j-1]\b
LOC(5,5)=10+[100(5-1)+5-1]2=818
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述大意了,没看到这题是以行为主。
BA+(4*10+7)*3,选A

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述注意:2-17错了,选B
在这里插入图片描述100+(7*8+4)*3=280,故选B

在这里插入图片描述注意:2-19又错了,选B

在这里插入图片描述10*(1+1+1)2+32=66

在这里插入图片描述

第四章

在这里插入图片描述
可以每层都是1
在这里插入图片描述满树
在这里插入图片描述
h=log(n+1)

在这里插入图片描述
格局小了,应该选F
在这里插入图片描述
用的是层次遍历
在这里插入图片描述
完全二叉树叶子结点只能出现在最下层和次下层,且最下层的叶子结点集中在树的左部。没有左孩子,那么一定没有右孩子
在这里插入图片描述
还可以用数组顺序存储。

如果i=1,则它是根节点;
如果i>1,则它的父节点的下标为i/2(向下取整);
如果2i<=n,则它的左子节点的下标为2i;
如果2i+1<=n,则它的右子节点的下标为2i+1。

在这里插入图片描述
用二叉链表存储,注意是唯一对应的
在这里插入图片描述
二叉链表存储,根节点因为没有兄弟,所以一定没有右子树
在这里插入图片描述
根据哈夫曼树的生成过程(不断选两个最小的树合并)可知,哈夫曼树没有度数为1的结点。
设度数为2的结点有n个,由二叉树的性质(度数为0的比2的多一个)得,度数为0的结点有n+1个,所以总结点数为2n+1

在这里插入图片描述
不知道哪错了,选F

在这里插入图片描述
树的度:度数最大结点的度数
所以二叉树不一定度为2
二叉树是一种特殊的有序树

在这里插入图片描述
在这里插入图片描述
哈夫曼树上层也可能出现叶子结点
哈夫曼树是最优二叉树,不一定是完全二叉树,也不一定是平衡二叉树(左右子树高度差不超1)

在这里插入图片描述
这两种遍历方法中无论哪个,右孩子一定是最后一个,若想先序和中序相同,那一定是去掉左孩子,只留根节点和右孩子,顺序是先根后右

在这里插入图片描述
在这里插入图片描述树没回路

在这里插入图片描述
要有相同的父节点才是兄弟

在这里插入图片描述到达根结点路径上的所有结点是祖先

在这里插入图片描述画个示意图易得要保留根结点和任一结点

在这里插入图片描述懒得找规律了,直接代特值d=2。按照顺序存储二叉树的方法,假想一颗层数为3的满二叉树,取3号结点,它的父结点为1,左孩子是6,右孩子是7,代入特值,只有C正确

在这里插入图片描述原本用栈是为了便于回溯,使用三叉链表可以直接通过双亲指针回溯

在这里插入图片描述随便画棵树,标号,再转成二叉树,遍历一下发现应选中序

在这里插入图片描述在这里插入图片描述用先序遍历确定每次的根结点,去分割中序遍历的序列,可得二叉树为(CDB)(FE)A,易得后序序列

在这里插入图片描述
在这里插入图片描述
森林转二叉树,第一棵树的根结点作为总根结点,第一棵树作为左子树,第二三棵树合成一下,再作为右子树连到总树上。所以右子树的根结点是m2+m3

在这里插入图片描述
已知2(h-1)=N,则由等比数列求和得2h-1=2N-1

在这里插入图片描述
在这里插入图片描述构建哈夫曼树,按查找长度及频次计算
在这里插入图片描述
在这里插入图片描述(33+43+53+63+82+102)/(3+4+5+6+8+10)=2.5
若漏算权重,会算出C2.67

在这里插入图片描述按图填回去字母,先序遍历一次得A

在这里插入图片描述构建哈夫曼树,得树高5
WPL=(2+3)*4+3*6+2*(12+7+10)=96

在这里插入图片描述总结点数为n,那就一共开了2n个指针,即总指针数2n。树的边数为n-1,即有n-1个非空的指针域,所以减一下得到空指针域是n+1个。2n-(n-1)=n+1

在这里插入图片描述(总度数=边数=n-1)=(Σ=10+2+30+80)
解得总结点数n=123,减去非叶子结点数41,得叶子结点数为82

在这里插入图片描述使结点数尽可能多且是完全二叉树,那么就要有6层,第5层有24=16个结点,其中有8个叶子结点,那么就有8个非叶子结点,所以第6层最多有2*8=16个结点。加上前面5层的总数25-1=31,得总结点数为47

在这里插入图片描述考查二叉树转回森林,从左向右按左倾的方向搜索,每次只需要每次将向右的线连回对应的根结点
在这里插入图片描述

在这里插入图片描述倒着看后序序列,去分割中序序列,还原出二叉树

在这里插入图片描述
在这里插入图片描述在这里插入图片描述总度数=n-1,n0=n-n1-n2-n3=8

在这里插入图片描述
后序遍历的最后一个元素是根结点
k是由中序序列得到的分解点,所以左子树在数组b中的终点是k-1,右子树的起点是k+1
由对数组b的分析可得左子树有k-1-s+1=k-s个元素,终点为i+k-s+1,同理右子树有t-k-1个元素,起点为j-t+k

在这里插入图片描述根据频率构建哈夫曼树,左0右1,写出每个字母的哈夫曼编码
WPL=5*(2+3)+4*4+3*7+2*22+3*(10+15)+2*37=255

在这里插入图片描述算成WPL了,W(T)=63

第六章

在这里插入图片描述
每条边都连接两定点产生两个度,总度和必为偶数

在这里插入图片描述边数大于等于顶点数-1

在这里插入图片描述
举个三角形图的例子

在这里插入图片描述设结点数为n,边数m,空间复杂度O(n+m)。只要两个节点之间有边相连,就会分配存储空间

在这里插入图片描述设结点数为n,边数m,空间复杂度O(n2)

在这里插入图片描述
在这里插入图片描述如果无向图G必须进行两次广度优先搜索才能访问其所有顶点,则G一定有2个连通分量(经过几次广度优先搜索,就有几个连通分量)

在这里插入图片描述若c到a小于10,则会更新b到a的最短路径距离

在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述假设刚开始有两条路径可以到达T,第一条上有1000条边,但总权值只有1,另一条只有一条权重为1.1的边,那么都加1时第一条路径实际增加了1000的权值

在这里插入图片描述最小生成树指的是整个路径最小,不是单个结点的路径最小

在这里插入图片描述直接记

在这里插入图片描述若e是最短边,则在Kruskal算法中,它必定会被先选中,被加入到最小生成树中

在这里插入图片描述深度优先算法

在这里插入图片描述在这里插入图片描述深度优先:前序遍历
广度优先:层次遍历

在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述选B

在这里插入图片描述选B

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

在这里插入图片描述

在这里插入图片描述在这里插入图片描述在这里插入图片描述以下代码来自acm佬@如沐晨光_

# include<bits/stdc++.h>
using namespace std;
const int N = 510;
const int inf = 1e9;
int g[N][N];
bool sex[N];
int d[N];
vector<int> a, b;
signed main() {
    int num;
    cin >> num;
    for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++) {
            if (i == j);
            else
                g[i][j] = inf;
        }
    for (int i = 1; i <= num; i++) {
        char se;
        int n;
        cin >> se >> n;
        if (se == 'F') sex[i] = 1;
        for (int j = 1; j <= n; j++) {
            int a, b;
            scanf("%d:%d", &a, &b);
            g[i][a] = min(g[i][a], b);
        }
    }
    for (int k = 1; k <= num; k++)
        for (int i = 1; i <= num; i++)
            for (int j = 1; j <= num; j++) {
                g[i][j] = min(g[i][k] + g[k][j], g[i][j]);
            }
    for (int i = 1; i <= num; i++)
        for (int j = 1; j <= num; j++)
            if (sex[i] != sex[j])
                d[i] = max(d[i], g[j][i]);
    int d1 = inf, d2 = inf;
    for (int i = 1; i <= num; i++)
    {
        if (sex[i]) d1 = min(d1, d[i]);
        else d2 = min(d2, d[i]);
    }

    for (int i = 1; i <= num; i++)
    {
        if (sex[i]) continue;
        if (d[i] == d2) a.push_back(i);
    }

    for (int i = 1; i <= num; i++)
    {
        if (!sex[i]) continue;
        if (d[i] == d1) b.push_back(i);
    }
    swap(a,b);
   printf("%d",a[0]); 
	for(int i=1;i<(int)a.size();i++) 
		printf(" %d",a[i]);	
	puts("");
	printf("%d",b[0]); 
	for(int i=1;i<(int)b.size();i++)
		printf(" %d",b[i]);
}

第七章(摆)

FTTTTF
BACDC DBBCA CD
转载自https://blog.csdn.net/BLADCS/article/details/105308961

bool Insert( List L, ElementType X ){
	if(L->Last==MAXSIZE-1) return false;
	if(L->Data[L->Last] > X){
		L->Data[L->Last+1]=X;
		L->Last++;
		return true;
	}
	int tp=0;int find=0;int tmp=0;
	for(int i=0;i <= L->Last;i++){
		if(L->Data[i] == X) return false;
		if(L->Data[i] < X && find==0){
			tp = L->Data[i];
			L->Data[i]=X;
			find=1;
		} 
		if(find==1){
			tmp=L->Data[i+1];
			L->Data[i+1]=tp;
			tp=tmp;
		}
	}
	L->Last++;
	return true;
}

第八章

在这里插入图片描述希尔选择冒泡插入快速排序O(n2),堆归并O(nlogn)

在这里插入图片描述在这里插入图片描述
对大文件排序(外部排序)时,多使用路归并排序
例如有一个含10000个记录的文件,首先通过10次内部排序得到10个初始归并段R1~R10 ,其中每一段都含1000个记录。然后对它们作如图所示的两两归并,直至得到一个有序文件为止。

在这里插入图片描述希尔排序和堆排序利用了顺序存储的随机访问特性

在这里插入图片描述快速排序的基本思想是分治思想,每次选择一个枢轴元素,将表中其他元素分成左右两部分,使左边部分的元素都小于等于枢轴元素,右边部分的元素都大于枢轴元素,然后递归地对左右两部分进行快速排序,直到所有子问题都变成了规模为 1 的问题为止。
如果原始数据已经有序,则每次选取的枢轴元素都会是当前序列中的最大或最小值,导致每次只能减少一个元素,执行效率极低,时间复杂度退化为 O(n2)。

在这里插入图片描述快速排序每趟确定的是枢轴元素,同时受到初始序列是否有序影响

在这里插入图片描述
n不论是左子树还是右子树,n的父结点一定是 [n/2],注意中括号的取整规则,正数就是下取整
那么 [n/2] 这个结点还是有子结点的,从 [n/2] + 1 开始一直到 n 都是叶子结点,叶子结点就可能会是最大值

在这里插入图片描述快速排序:平均O(nlogn),最坏O(n2)

在这里插入图片描述最后一个元素正好应该排最前面,插入排序最后一趟所有元素都要后移

在这里插入图片描述希尔排序每趟排好的是“内序”

在这里插入图片描述
插入排序通过构建有序序列,让未排序数据插入

在这里插入图片描述选择排序很呆,不管初始有序无序都要全跑一遍
而冒泡排序如果初始有序,则一个泡也冒不出来,即一次可以结束

在这里插入图片描述在这4种排序算法中,需要的辅助空间最大的是归并排序。因为归并排序需要用到 O(n) 的辅助空间来存储每一次合并操作所需的过程值,以及最后合并时临时存储所有数组元素的辅助数组。而选择排序和快速排序不需要额外空间,希尔排序只需要O(1)的额外空间(也有一些变种需要较多辅助空间)

在这里插入图片描述
不稳定的排序:选择,快速,希尔,堆

在这里插入图片描述

在这里插入图片描述稳定的排序:插入,气泡,归并
O(nlogn)的:归并,堆,希尔,快速

在这里插入图片描述注意到4,8,15的位置改变方式,显然是希尔排序

在这里插入图片描述选最前面的10个数,只有冒泡和堆排序可以10次解决问题,同时堆排速度快

在这里插入图片描述快速排序:以28为界分成两部分,前小后大,然后取r,f指针,从后向前搜索,当f的值大于r则交换,并换一头搜索,直到r,f重合,此时一次划分结束

在这里插入图片描述
在这里插入图片描述
小顶堆:放入二叉树后,所有分支<=孩子结点关键码

在这里插入图片描述在这里插入图片描述
在这里插入图片描述尽管初始有序也要全部循环完

在这里插入图片描述堆排序和冒泡排序里选到更快的堆排序

在这里插入图片描述在这里插入图片描述初始时完全逆序,比较总数即为n-1加到1

在这里插入图片描述归并排序每趟排的是子序列中的内序

在这里插入图片描述初始逆序,冒泡排序比较n(n-1)/2次

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述选择排序:直接选择,堆排序

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述在这里插入图片描述
在这里插入图片描述快速排序要快速确定子区间,所以要用到随机访问特性,即顺序存储

在这里插入图片描述
归并和直接插入稳定,直接插入O(n2),二路归并O(nlogn)

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
按快速排序跑一趟发现左右指针在81相遇,即枢轴元素是81,选D

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值