数据结构刷题
文章目录
- 数据结构刷题
- 计算时间复杂度练习题
- 答案
- 不带头结点的单链表的插入和删除运算
- 数据结构头插法和尾插法建立单链表
- 二叉树各种方法实现
- 数据结构图的练习题
- 习题
- 答案
- 习题
计算时间复杂度练习题
1、设 n 为正整数。试确定下列各程序段中前置以记号@的语句的频度。
(1)
i = 1;
k = 0;
while(i <= n-1)
{
@ k += 10*i;
i++;
}
(2)
k = 0;
for(i = 1; i <= n; i++)
{
for(j = i; j <= n; j++)
@ k++;
}
(3)
for(i = 1; i <= n; i++)
{
for(j = 1; j <= i; j++)
{
for(k = 1; k <= j; k++)
@ x += delta;
}
}
2、假设n为2的乘幂,并且 n > 2,试求下列算法的时间复杂度及变量 count 的值(以n的函数形式表示)并写出计算过程。
int Time(int n)
{
int count = 0;
int x = 2;
while(x < n/2)
{
x *= 2;
count ++;
}
return (count);
}//Time
程序作业
已知 k 阶斐波那契序列的定义为:
试编写求 k 阶斐波那契序列的第 m 项值的函数算法,k 和 m 均以值调用的形式在函数参数表中出现。请写出算法的时间复杂度。
答案
1、
2、
1.
Status Fibonacci(int k, int m, int &f)
2. /* 求k阶斐波那契序列的第m项的值f */
3. {
4. int sum,i,j,e[100];
5. if(k < 2||m < 0) return ERROR; /**异常处理**/
6. /**
7. 根据k阶斐波那契序列的定义:
8. K阶斐波那契数列的前K-1项均为0,
9. 第k项为1,以后的每一项都是前K项的和
10. **/
11. if(m < k-1)
12. f = 0;
13. else if(m == k-1)
14. f = 1;
15. else{
16. for(i = 0;i < k-1;i++)
17. e[i] = 0; //K阶斐波那契数列的前K-1项均为0
18. e[k-1] = 1; //第k项为1
19. for(i = k;i <= m;i++){
20. sum = 0;
21. for(j = i-k;j <= i;j++)//以后的每一项都是前k项的和
22. sum += e[j];
23. e[i] = sum; //将以后的每一项的值存进数组e中
24. }
25. f = e[m]; //求k阶斐波那契序列的第m项的值f
26. }
27. return OK;
28. }
不带头结点的单链表的插入和删除运算
int ListInsert(LinkList &L,int i,int e)
{ // 在不设头结点的单链线性表L中第i个位置之前插入元素e
int j=1; // 计数器初值为1
LinkList s,p=L; // p指向第1个结点
if(i<1) // i值不合法
return 0;
s=(LinkList)malloc(sizeof(LNode)); // 生成新结点,以下将其插入L中
s->data=e; // 给s的data域赋值e
if(i==1) // 插在表头
{ s->next=L; // 新结点指向原第1个结点
L=s; // L指向新结点(改变L)
}
else
{ // 插在表的其余处
while(p&&j<i-1) // 寻找第i-1个结点
{ j++; // 计数器+1
p=p->next; // p指向下一个结点
}
if(!p) // i大于表长+1
return 0; // 插入失败
s->next=p->next; // 新结点指向原第i个结点
p->next=s; // 原第i-1个结点指向新结点
}
return 1; // 插入成功
}
//不带头结点的删除运算
int ListDelete(LinkList &L,int i,int &e)
{ // 在不设头结点的单链线性表L中,删除第i个元素,并由e返回其值
int j=1; // 计数器初值为1
LinkList q,p=L; // p指向第1个结点
if(!L) // 表L空
return 0; // 删除失败
else if(i==1) // 删除第1个结点
{ L=p->next; // L由第2个结点开始(改变L)
e=p->data; // 将待删结点的值赋给e
free(p); // 删除并释放第1个结点
}
else
{ while(p->next&&j<i-1) // 寻找第i个结点,并令p指向其前驱
{ j++; // 计数器+1
p=p->next; // p指向下一个结点
}
if(!p->next||j>i-1) // 删除位置不合理
return 0; // 删除失败
q=p->next; // q指向待删除结点
p->next=q->next; // 待删结点的前驱指向待删结点的后继
e=q->data; // 将待删结点的值赋给e
free(q); // 释放待删结点
}
return 1; // 删除成功
}
数据结构头插法和尾插法建立单链表
#include <stdlib.h>
#include<stdio.h>
typedef struct node
{
int data;
struct node *next;
}*Listlink;
/*前插法创建单链表*/
void qian_create(Listlink *head,int n)
{
int i;
Listlink p;
*head=(Listlink )malloc(sizeof(struct node));
(*head)->next=NULL;/*建立头结点*/
printf("input %d numbers:\n",n);
for(i=0;i<n;i++)
{
p=(Listlink)malloc(sizeof(struct node));
scanf("%d",&(p->data));
p->next=(*head)->next;
(*head)->next=p;
}
}
/*后插法创建单链表*/
void hou_create(Listlink *head,int n)
{
int i;
Listlink p,q;
*head=(Listlink )malloc(sizeof(struct node));
(*head)->next=NULL;/*建立头结点*/
q=*head;
for(i=0;i<n;i++)
{
p=(Listlink)malloc(sizeof(struct node));
scanf("%d",&(p->data));
p->next=q->next;
q->next=p;
q=p;
}
}
void print_list(Listlink head)
{
Listlink p;
p=head->next;
while(p!=NULL)
{
printf(" %d",p->data);
p=p->next;
}
}
main()
{
Listlink la,lb,lc;
puts("houcha:");
hou_create(&lb,10);
puts("qiancha:");
qian_create(&la,10);
print_list(la);
print_list(lb);
getchar();
}
二叉树各种方法实现
#include <stdio.h>
#include <malloc.h>
#define MAXSIZE 20
//二叉树结点的结构体表示形式
typedef struct node
{
char data;
struct node* left,*right;
}BTree;
//栈的结构体表示形式
typedef struct stackelem
{
BTree* a[MAXSIZE];
int top;
}Stack;
//队列的结构体的表示形式
typedef struct queueelem
{
BTree* b[MAXSIZE];
int front,rear;
}Queue;
//创建二叉树,利用递归的方法
BTree* Create()
{
char ch;
scanf("%c",&ch);
getchar();
if (ch=='#')
{
return NULL;
}
else
{
BTree* btree=(BTree*)malloc(sizeof(BTree));
if (btree==NULL)
{
return NULL;
}
btree->data=ch;
btree->left=Create();
btree->right=Create();
return btree;
}
}
//求二叉树的高度,递归实现
int Height(BTree* bt)
{
int depth1,depth2;
if (NULL==bt)
{
return 0;
}
else
{
depth1=Height(bt->left);
depth2=Height(bt->right);
if (depth1>depth2)
{
return (depth1+1);
}
else
{
return (depth2+1);
}
}
}
int Width(BTree *T)//二叉树宽度
{
int static n[10];//向量存放各层结点数
int static i=1;
int static max=0;//最大宽度
if(T)
{
if(i==1) //若是访问根结点
{
n[i]++; //第1层加1
i++; //到第2层
if(T->left)//若有左孩子则该层加1
n[i]++;
if(T->right)//若有右孩子则该层加1
n[i]++;
}
else
{ //访问子树结点
i++; //下一层结点数
if(T->left)
n[i]++;
if(T->right)
n[i]++;
}
if(max<n[i])max=n[i];//取出最大值
Width(T->left);//遍历左子树
i--; //往上退一层
Width(T->right);//遍历右子树
}
return max;
}
//层次遍历二叉树,用队列来实现
void TraversalOfLevel(BTree* bt)
{
Queue q;
q.front=q.rear=0;
if (bt!=NULL)
{
printf("%c ",bt->data);
}
q.b[q.front]=bt;
q.rear=q.rear+1;
while (q.front<q.rear)
{
bt=q.b[q.front];
q.front=q.front+1;
if (bt->left!=NULL)
{
printf("%c ",bt->left->data);
q.b[q.rear]=bt->left;
q.rear=q.rear+1;
}
if (bt->right!=NULL)
{
printf("%c ",bt->right->data);
q.b[q.rear]=bt->right;
q.rear=q.rear+1;
}
}
}
int leafcount(BTree* root)//统计叶子结点个数
{
if(root==NULL) return 0 ;
else
{
if(!root->right&&!root->left) return 1;
else return leafcount(root->left)+leafcount(root->right);
}
}
int CountNode (BTree *t) //节点总数
{
int num;
if (t == NULL)
num = 0;
else
num = 1 + CountNode (t->left) + CountNode (t->right);
return (num);
}
BTree *copy(BTree *p) // 复制一棵二叉树
{
BTree *temp;
if(p==NULL)
return NULL;
temp=(BTree *)malloc(sizeof(BTree));
temp->data=p->data;
temp->left=copy(p->left);
temp->right=copy(p->right);
return temp;
}
/* 判断两棵二叉树是否相似的递归算法 */
int Similar(BTree *t1, BTree *t2)
{
if(t1==NULL&&t2==NULL) return 1;
if(t1&&t2)
{
if(Similar(t1->left,t2->left)&&Similar(t1->right,t2->right))
{
return 1;
}
}
return 0;
}
int CompTree(BTree *tree1,BTree *tree2)//二叉树是否相等
{
if (!tree1 && !tree2)
{
return 1;
}
else if (tree1->data == tree2->data &&
CompTree(tree1->left, tree2->left) &&
CompTree(tree1->right, tree2->right))
{
return 1;
}
else
{
return 0;
}
}
int main()
{
BTree* btr=Create();
printf("叶子结点个数为:\n");
int leafgs=leafcount(btr);
printf("%d \n",leafgs);
printf("结点总数为:\n");
int countn=CountNode(btr);
printf("%d \n",countn);
printf("度为1的结点个数为:%d\n",countn-2*leafgs+1);
printf("度为2的结点个数为:%d\n",leafgs-1);
printf("二叉树的高度:\n");
int Hgt=Height(btr);
printf("%d \n",Hgt);
printf("二叉树的宽度:\n");
int Wdh=Width(btr);
printf("%d \n",Wdh);
printf("层次遍历二叉树:\n");
TraversalOfLevel(btr);
printf("\n");
printf("复制的二叉树为:\n");
BTree * cp=copy(btr);
TraversalOfLevel(cp);
printf("\n");
if(Similar(btr,cp)==1)
printf("此两二叉树相似\n");
else printf("此两二叉树不相似\n");
if(CompTree(btr,cp)==1)
printf("此两二叉树相等\n");
else printf("此两二叉树不相等\n");
return 0;
}
数据结构图的练习题
一、 选择题
- 图中有关路径的定义是( A)
A. 由顶点和相邻顶点序偶构成的边所形成的序列
B. 由不同顶点所形成的序列
C. 由不同边所形成的序列
D. 上述定义都不是 - 一个有n个顶点和n条边的无向图一定是( D )
A. 连通的
B. 不连通的
C. 无环的
D. 有环的 - 下列关于无向连通图特性的叙述中,正确的是( A )
I. 所有顶点的度之和为偶数
II. 边数大于顶点数减一
III. 至少有一个顶点的度为1
A. 只有Ⅰ
B. 只有Ⅱ
C. Ⅰ和Ⅱ
D. Ⅱ和Ⅲ - 若无向图G={V,E}中含有7个顶点,要保证图G在任何情况下都是连通的,则需要的边数至少是(C )
A. 6
B. 15
C. 16
D. 21 - 已知无向图G含有16条边,其中度为4的顶点个数为3,度为3的顶点个数为4,其他顶点的度均小于3.图G所含的顶点个数至少是(B )
A. 10
B. 11
C. 13
D. 15 - 对有n个顶点,e条边且使用邻接表存储的有向图进行广度优先遍历,其算法的时间复杂度是( C )
A. O(n)
B. O(e)
C. O(n+e)
D. O(n*e) - 使用迪杰斯特拉算法求下图中从顶点1到其他各顶点的最短路径,依次得到的各最短路径的目标顶点是(B )
A. 5,2,3,4,6
B. 5,2,3,6,4
C. 5,2,4,3,6
D. 5,2,6,3,4
二、 综合题 - 已知含有5个顶点的图G如下图所示。
请回答问题:
- 写出图G的邻接矩阵A(行、列下标从0开始)。
- 求A2,矩阵A2中位于0行3列元素值的含义是什么?
- 若已知具有n(n>=2)个顶点的图的邻接矩阵为B,则Bm中(2<=m<=n)非零元的含义是什么?
答案:
- 如下图所示,一个用AOE网表示的工程。
试回答:
- 画出此图的邻接表表示。
- 完成此工程,至少需要多少时间。(16)
- 指出关键路径。(1-3-5-7-9)
- 哪些活动加速可以缩短完成工程所需的时间?(a2-a6-a9-a12)
习题
-
已知一个6´5稀疏矩阵如下所示,试写出:
(1) 写出它的三元组线性表;
(2) 给出三元组线性表的顺序存储表示。
-
设有一个输入数据的序列是 { 46, 25, 78, 62, 12, 80 }, 试画出从空树起,逐个输入各个数据而生成的二叉搜索树。
-
已知一棵二叉树的前序遍历的结果序列是ABECDFGHIJ,中序遍历的结果是EBCDAFHIGJ,试写出这棵二叉树的后序遍历结果。
-
设给定一个权值集合W=(3,5,7,9,11),要求根据给定的权值集合构造一棵哈夫曼树并计算哈夫曼树的带权路径长度WPL。
对于图6所示的有向图若存储它采用邻接表,并且每个顶点邻接表中的边结点都是按照终点序号从小到大的次序链接的,试写出:
(1) 从顶点①出发进行深度优先搜索所得到的深度优先生成树;
(2) 从顶点②出发进行广度优先搜索所得到的广度优先生成树;
6. 已知一个图的顶点集V和边集E分别为:
V={1,2,3,4,5,6,7};
E={<2,1>,❤️,2>,❤️,6>,<4,3>,<4,5>,<4,6>,<5,1>,<5,7>,<6,1>,<6,2>,<6,5>};
若存储它采用邻接表,并且每个顶点邻接表中的边结点都是按照终点序号从小到大的次序链接的,按主教材中介绍的拓朴排序算法进行排序,试给出得到的拓朴排序的序列。
7. 已知一个图的顶点集V各边集G如下:
V = {0,1,2,3,4,5,6,7,8,9};
E = {(0,1),(0,4),(1,2),(1,7),(2,8),(3,4),(3 ,8),(5,6),(5,8),(5,9),(6,7),(7,8),(8,9)}
当它用邻接矩阵表示和邻接表表示时,分别写出从顶点V0出发按深度优先搜索遍历得到的顶点序列和按广度优先搜索遍历等到的顶点序列。
假定每个顶点邻接表中的结点是按顶点序号从大到小的次序链接的。
8. 设无向图G(所右图所示),要求给出该图的深度优先和广度优先遍历的序列并给出该图的最小生成树。
9. 一个线性表为B=(12,23,45,57,20,03,78,31,15,36),设散列表为HT[0…12],散列函数为H(key)= key % 13并用线性探查法解决冲突,请画出散列表,并计算等概率情况下查找成功的平均查找长度。
10. 设一组初始记录关键字集合为(25,10,8,27,32,68),散列表的长度为8,散列函数H(k)=k mod 7,要求分别用线性探测和链地址法作为解决冲突的方法设计哈希表并计算平均查找长度。
11. 已知一组记录的排序码为(46,79,56,38,40,80, 95,24),写出对其进行快速排序的每一次划分结果。
12. 设一组初始记录关键字序列为(19,21,16,5,18,23),要求给出以19为基准的一趟快速排序结果以及第2趟直接选择排序后的结果。
13. 依次把结点(34,23,15,98,115,28,107)插入到初始状态为空的平衡二叉排序树中,使得在每次插入后保持该树仍然是平衡二叉树。请依次画出每次插入后所形成的的平衡二叉排序树。
答案
- ((1,5,1),(3,2,-1),(4,5,-2),(5,1,5),(6,3,7))
5、
DFS:①②③④⑤
BFS:②③④⑤①
6、
4 3 6 5 7 2 1
7、
11、
24,40,38,46,56,80,95,79
24,40,38,46,56,80,95,79
24,38,40,46,56,80,95,79
24,38,40,46,56,79,80,95
习题
一、 选择题
- 设一维数组中有n个数组元素,则读取第i个数组元素的平均时间复杂度为( )
A. O(n)
B. O(nlog2n)
C. O(1)
D. O(n2) - 设二叉树的先序遍历序列和后序遍历序列正好相反,则该二叉树满足的条件是( )
A. 空或只有一个结点
B. 高度等于其结点树
C. 任一结点无左孩子
D. 任一结点无右孩子 - 设一组初始记录关键字序列为(13,18,24,35,47,50,62,83,90,115,134),则利用二分法查找关键字90需要比较的关键字个数为( )
A. 1
B. 2
C. 3
D. 4 - 下列各种排序算法中平均时间复杂度为O(n2)是( )
A. 快速排序
B. 堆排序
C. 归并排序
D. 冒泡排序 - 设输入序列1、2、3、…、n-1、n经过栈作用后,输出序列中的第一个元素是n,则输出序列中第i个输出元素是( )
A. n-i
B. n-1-i
C. n+1-i
D. 不能确定 - 设无向图G中变的集合E={(a,b),(a,e),(a,c),(b,e),(e,d),(d,f),(f,c)},则从顶点a出发进行深度优先遍历可以得到的一种顶点序列为( )
A. aedfcb
B. acfebd
C. aebcfd
D. aedfbc - 设按照从上到下,从左到右的顺序从1开始对完全二叉树进行顺序编号,则编号为i结点的左孩子结点的编号是( )
A. 2i+1
B. 2i
C. i/2
D. 2i-1 - 设某哈夫曼树中有199个结点,则该哈夫曼树中有()个叶子结点。
A. 99
B. 100
C. 101
D. 102 - 若有18个元素的有序表存放在一维数组A[19]中,第一个元素放A[1]中,现进行二分查找,则查找A[3]的比较序列的下标依次为()
A. 1,2,3
B. 9,5,2,3
C. 9,5,3
D. 9,4,2,3 - 下列二叉排序树中,满足平衡二叉树定义的是()
- 串是一种特殊的线性表,其特殊性体现在( )。
A、可以顺序存储
B、数据元素是一个字符
C、可以链接存储
D、数据元素可以是多个字符 - 求整数n(n≥0)阶乘的算法如下,其时间复杂度是( )。
int fact( int n )
{
if(n<=1) return 1;
return n * fact(n - 1);
}
A.O(log2n) B. O(n2) C. O(n log2n) D. O(n) - 以下哪个术语与存储结构无关( )。
A.循环队列 B.链表 C.哈希表 D.栈 - 循环队列存储在数组A[0…m]中,则入队是的操作为()。
A. rear=rear+1 B.rear=(rear+1)mod(m-1)
C. rear=(rear+1)mod m D.rear=(rear+1)mod(m+1) - 对于下列关键字序列,不可能构成某二叉排序树中一条查找路径的序列()
A.95,22,91,24,94,71
B.92,20,91,34,88,35
C.21,89,77,29,36,38
D.12,25,71,68,33,34
答案:CBBDC ABBDB BDDDA
二、 填空题 - 假定一棵树的广义表表示为A(C,D(E,F,G),H(I,J)),则树中所含的结点数为( )个,树的深度为( ),树的度为( )。
- 对于一个具有n个顶点和e条边的有向图和无向图,在其对应的邻接表中,所含边结点分别有( )个和( )个。
- 在快速排序、堆排序、归并排序中,( )排序是稳定的。
- 设一组初始记录关键字序列为(13,18,24,35,47,50,62,83,90,115,134),则利用二分法查找关键字90需要比较的关键字个数为( )
- 设前序遍历某二叉树的序列为ABCD,中序遍历该二叉树的序列为BADC,则后序遍历该二叉树的序列为( )
- 设有向图G的存储结构用邻接矩阵A来表示,则A中第i行中所有非零元素个数之和等于顶点i的( ),第i列中所有非零元素个数之和等于顶点i的( )
- 广义表(((a,b,(),c),d),e,((f),g))的长度是____,深度是_____。
- 在二维数组A中,设每个数组元素的长度为3个存储单元,行下标i从0到8,列下标j从0到9,从首地址SA开始按行连续存放。在这种情况下,元素A[8][5]的起始地址为_________。
答案:
1、9 3 3
2、e 2e
3、归并排序
4、2
5、BDCA
6、出度 入度
7、3 4
8、SA+255
三、 简答题 - 将关键字序列(7、8、30、11、18、9、14)散列存储到散列列表中,散列表的存储空间是一个下标从0开始的一个一维数组,散列函数为:H(key)=(key×3)MOD 7,处理冲突采用线性探测再散列法,要求装填(载)因子为0.7。
问题:
①、请画出所构造的散列表;
②、分别计算等概率情况下,查找成功。
①、由装载因子0.7,数据总数7个,所以储空间长度为10。所以,构造的散列表的哈希地址为:
H(7)=(73)MOD7=0
H(8)=(83)MOD7=3
H(11)=(113)MOD7=5
H(18)=(183)MOD7=5
H(9)=(93)MOD7=6
H(14)=(143)MOD7=0
H(30)=(30*3)MOD7=6
根据哈希地址可以得出如下图所示的哈希表。
②、平均查找长度
查找成功的平均查找长度:ASL成功 =(1+1+1+1+2+3+3)/7=12/7。
查找不成功的平均查找长度:ASL不成功 =(3+2+1+2+1+5+4)/7=18/7。
2. 已知无向网G的邻接矩阵如下图所示,顶点依次是V1,V2,V3,V4,V5,V6,V7,V8,要求:
(1) 请画出该网。
(2) 按克鲁斯卡尔算法给出网G的最小生成树的生成过程。
(1)、无向网。
(4)
(2)、克鲁斯卡尔算法生成最小生成树的过程。