转存失败重新上传取消
(2)二叉树先序遍历序列为 + * 8 + 2 3 / + 4 5 - 9 6
(3)后缀表达式为:8 2 3 + * 4 5 + 9 6 - / +
(4)Push(8); Push(2); Push(3); Pop(); Pop(); Push(5); Pop(); Push(40); Push(4); Push(5); Pop(); Pop(); Push(9); Push(9); Push(6); Pop(); Push(3); Pop(); Pop(); Push(3); Pop(); Pop(); Push(43); Pop();
深度最小为4。
(5)层序遍历序列为:+ * / 8 + + - 2 3 4 5 9 6。
(6)7
(7)栈(Stack)是限定只能在表的一端进行插入和删除操作的线性表。队列(Queue)是限定只能在表的一端进行插入和在另一端进行删除操作的线性表。栈必须按"后进先出"的规则进行操作,而队列必须按"先进先出"的规则进行操作。
1问:
① 顺序存储时,相邻数据元素的存放地址也相邻(逻辑与物理统一);要求内存中可用存储单元的地址必须是连续的。
优点:存储密度大(=1),易于查找和修改。
缺点:插入或删除元素时不方便;存储空间利用率低,预先分配内存可能造成存储空间浪费。
②链式存储时,相邻数据元素可随意存放,但所占存储空间分两部分,一部分存放结点值,另一部分存放表示结点间关系的指针
优点:插入或删除元素时很方便,使用灵活,存储空间利用率高。
缺点:存储密度小(<1),查找和修改需要遍历整个链表。
从使用情况比较,顺序表适宜于做查找这样的静态操作;链表宜于做插入、删除这样的动态操作。若线性表的长度变化不大,且其主要操作是查找,则采用顺序表;若线性表的长度变化较大,且其主要操作是插入、删除操作,则采用链表。
比较
顺序表与链表的比较,首先基于空间的比较,顺序表和链表的存储空间均为O(n)。按存储分配的方式比较,顺序表的存储空间是静态分配的,链表的存储空间是动态分配的,若存储密度 = 结点数据本身所占的存储量/结点结构所占的存储总量,则顺序表的存储密度 = 1,链表的存储密度 < 1。
基于时间的比较按存取方式比较,顺序表可以随机存取,也可以顺序存取。链表是顺序存取的,插入/删除时移动元素个数比较,顺序表平均需要移动近一半元素,链表不需要移动元素,只需要修改指针
2问:对数据的主要操作是读操作,顺序存储查询效率更高。
3问:更适合链式存储,链式存储分配的内存不连续,当删除,增加或者修个一个数据,不需要移动整张表,只需要修改指针即可。
4问:顺序查找和二分查找的时间复杂度分析:
顺序查找需要遍历整个表,直到找到需要的数据即可,时间复杂度为O(n)二分查找的时间复杂度为:总共有n个元素,每次查找的区间大小就是n,n/2,n/4,…,n/2^k(接下来操作元素的剩余个数),其中k就是循环的次数。
由于n/2^k取整后>=1,即令n/2^k=1,
可得k=log2n,(是以2为底,n的对数),所以时间复杂度可以表示O()=O(log2n)
(本小题给出两个正确的时间复杂度即可得3分,有分析可得4分)
5问:答:要求算法稳定应该选择冒泡排序
原因(原因可答可不答):
(1)冒泡排序是比较相邻位置的两个数,而选择排序是按顺序比较,找最大值或者最小值;
(2)冒泡排序每一轮比较后,位置不对都需要换位置,选择排序每一轮比较都只需要换一次位置;
(3)冒泡排序是通过数去找位置,选择排序是给定位置去找数;
冒泡排序优缺点:优点:比较简单,空间复杂度较低,是稳定的;
缺点:时间复杂度太高,效率慢;
选择排序优缺点:优点:一轮比较只需要换一次位置;
缺点:效率慢,不稳定伪代码:
要求根据成绩对学生排序伪代码:(写出了StudentScoreSort函数的内容即可得分,不限编程语言,伪代码亦可;排序可以从小到大,也可以从大到小。)
定义一个结构体代表一个学生实体:
struct Student
{
public int num;
public string Code;
public string Name;
public decimal Score;
}
static void Main(string[] args)
{
ArrayList list = new ArrayList();
Student stu = new Student;
从控制台输入学生的相关信息
List.add(stu)
Print(“-----------------------学生数据展示--------------------------”)
for (int i = 1; i < list.size(); i++)
{
打印学生的相关信息
}
对学生信息排序调用
StudentScoreSort(list,int length)
printStudent(){
For(list list: list){
Print(“排序好的学生信息”)
}
}
}
List StudentScoreSort(list,int length)
{
for (int i = 0; i < list.Count - 1; i++)
{
for (int j = i + 1; j < list.Count-i-1; j++)
{
Student s1 = (Student)list[i];
Student s2 = (Student)list[j];
if (s1.Score < s2.Score)
{
交换两条记录的位置
}
}
}
}
三、(10分)
哈希表:
哈希地址 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
关键字 | 7 | 1 | 16 | 30 | 91 | 48 | 62 | 20 | ||
冲突次数 | 0 | 0 | 0 | 1 | 4 | 0 | 1 | 2 |
2问:
查找成功的平均查找次数ASL=(1+1+1+2+5+1+2+3)/8=2
查找失败的平均查找次数为 ASL=(6+5+4+3+2+1+4+3+2+1)/10 = 3.1
(1)
转存失败重新上传取消
(2)根节点从1开始,Huffman树的高度为5。
(3)wpl =(2+3)*4+6*3+(12+7+10)*2=96
(1)要求全部连通且路径最优可以选择最小生成树算法/Prim算法/Kruskal算法(答出其中之一即可)。
(2)
prim算法:
从最左上角的顶点C出发,从初始只有这个顶点的当前树开始,不断加入边和相关顶点到树中使得当前树不断增长,最终成为一颗最小生成树。
若从C出发 最小生成树的节点集合计为 prim={}
步骤 | 路径 | 代价 | 记录的节点集合 |
1 | c->f | 120 | {c,f} |
2 | f->s | 150 | {c,f,s} |
3 | s->a | 160 | {c,f,s,a} |
4 | a->g | 50 | {c,f,s,a,g} |
5 | g->b | 70 | {c,f,s,a,g,b} |
6 | b->j | 80 | {c,f,s,a,g,b,j} |
7 | a->d | 170 | {c,f,s,a,g,b,j,d} |
8 | d->e | 90 | {c,f,s,a,g,b,j,d,e} |
9 | e->q | 100 | {c,f,s,a,g,b,j,d,e,q} |
Kruskal算法:
步骤 | 路径 | 代价 | 记录的节点集合 |
1 | a->g | 50 | {a,g} |
2 | g->b | 70 | {a,g,b} |
3 | b->j | 80 | {a,g,b,j} |
4 | e->d | 90 | {a,g,b,j,e,d} |
5 | e->q | 100 | {a,g,b,j,e,d,q} |
6 | c->f | 120 | {a,g,b,j,e,d,q,c,f} |
7 | f->s | 150 | {a,g,b,j,e,d,q,c,f,s} |
8 | s->a | 160 | {a,g,b,j,e,d,q,c,f,s} |
9 | a-d | 170 | {a,g,b,j,e,d,q,c,f,s} |
转存失败重新上传取消
最小生成树
(3)
Dijkstra算法(2分)
(计算过程用文字、表格、图皆可,结果正确可得4分,如有错误酌情扣分。)
FC F->C 120
FE F->E 280
FQ F->E->Q 380
FS F->S 150
FD F->D 250
FA F->A 300
FG F->A->G 350
FB F->A->G->B 420
FJ F->A->J 420
转存失败重新上传取消
转存失败重新上传取消
(4):
深度优先:ADEFCQSGBJ
广度优先:ADFGJSECBQ