复习笔记6_数据结构线性表(强化习题)

习题纠错:

在下面的程序段中,对x的赋值语句的频度为: n(n+1)(n+2)/6 (表示为 n 的函数)

for(int i=1;i<=n;i++)
    for(int j=1;j<=i;j++)
        for(int k=1;k<=j;k++)
   	          x=x+1; 

最暴力的方法就是穷举,但是比较麻烦,在看到答案的时候其实就会有一种猜测:对于这种类型的for循环有 i 重频度就为:n * ( n + 1 ) * ...... * ( n + i - 1 )/ i!
特别的二重就是:n * (n + 1) / 2
三重就是:n * (n + 1) * (n + 2) / 6
四重就是:n * (n + 1) * (n + 2) * (n + 3) / 24
可以用数学归纳法证明一遍,但是为了方便直接通过下面代码的执行来直观的观察。(虽然只到了第五重)

// 时间复杂度.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
using namespace std;

void fuzadu1(int n) {
    cout << n * (n + 1) * (n + 2) / 6 << endl;
    int x = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= i; j++) {
            for (int k = 1; k <= j; k++) {
                x++;
            }
        }
    }
    cout << x << endl;
}

void fuzadu2(int n) {
    cout << n * (n + 1) * (n + 2) * (n + 3) / 24 << endl;
    int x = 0;
    for(int m=1;m<=n;m++)
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= i; j++) {
                for (int k = 1; k <= j; k++) {
                    x++;
                }
            }
        }
    cout << x << endl;
}

void fuzadu3(int n) {
    cout << n * (n + 1) * (n + 2) * (n + 3) * (n + 4) / (24 * 5) << endl;
    int x = 0;
    for (int z = 0; z <= n; z++) 
        for (int m = 1; m <= z; m++) 
            for (int i = 1; i <= m; i++) {
                for (int j = 1; j <= i; j++) {
                    for (int k = 1; k <= j; k++) {
                        x++;
                    }
                }
            }
    cout << x << endl;
}


int main()
{
    fuzadu1(10);
    fuzadu2(10);
    fuzadu3(10);
    return 0}


1、设顺序表用数组A[]表示,表中元素存储在数组0~m+n-1 的范围内,前m个元素递增,后n个元素递增,设计 算法使整个设计表有序。

(1) 给出算法的基本设计思想。
(2) 根据设计思想,采用C或C++语言描述算法,并在关键之处给出注释。
(3) 说明你 所设计的算法的时间复杂度。

(1)给出算法的基本设计思想。

  • 传参:数组A[],m表示前m个数,n表示共有n个数。
  • 定义r表示数组B[]的下标,定义i,j为数组A[]下标。
  • 将数组的A[ i ]同A[ j ]比较,小的存入数组B
  • 若数组A的前m个数未遍历完,将剩余的数依次全部存入B
  • 若数组A的后n个数未遍历完,将剩余的数依次全部存入B

(2)根据设计思想,采用C或C++语言描述算法,并在关键之处给出注释。

void merge(int A[],int m,int n) {
	int B[max];
	int r = 0;int i = 0; int j = m;
	while (i < m && j < n) {    //将数组的A[ i ]同A[ j ]比较,小的存入数组B
		if (A[i] < A[j]) {
			B[r++] = A[i++];
		}
		else {
			B[r++] = A[j++];
		}
	}
	while (i < m) {   //若数组A的前m个数未遍历完,将剩余的数依次全部存入B
		B[r++] = A[i++];
	}
	while (j < n) {   //若数组A的后n个数未遍历完,将剩余的数依次全部存入B
		B[r++] = A[j++];
	}
	for (int i = 0; i < r; i++) {
		A[i] = B[i];
	}
}

(3)说明你 所设计的算法的时间复杂度。
时间复杂度:O(n)

源码:

#include<iostream>
using namespace std;
#define eletype int
#define max 50

void init(int A[],int& m,int &n) {
	for (int i = 0; i < 10; i++) {
		A[i] = i * 2 + 1;
		m++;
	}
	n += m;
	for (int i = 10; i < 20; i++) {
		A[i] = (i-10) * 2;
		n++;
	}
}

void printList(int A[],int n) {
	for (int i = 0; i < n; i++) {
		cout << A[i] << " ";
	}
	cout << endl;
}

void merge(int A[],int m,int n) {
	int B[max];
	int r = 0;int i = 0; int j = m;
	while (i < m && j < n) {
		if (A[i] < A[j]) {
			B[r++] = A[i++];
		}
		else {
			B[r++] = A[j++];
		}
	}
	while (i < m) {
		B[r++] = A[i++];
	}
	while (j < n) {
		B[r++] = A[j++];
	}
	for (int i = 0; i < r; i++) {
		A[i] = B[i];
	}
}

int main() {
	int A[max];
	int n = 0;
	int m = 0;
	init(A,m,n);
	printList(A,n);
	merge(A,m,n);
	printList(A, n);
	return 0;
}


答案:
(1) 算法的基本设计思想:

将数组A [] 中的m+n个元素(假设元素为int型)看成两个顺序表:表L和表R。将数组当前状态看作是 起始状态,即此时表L由A[]中前m个元素构成,表R由A[]中后n个元素构成。要使A[]中m+n个元素整体有 序,只需将表R中的元素逐个插入表L中的合适位置即可。

插入过程:取表R中的第一个元素A[m+1]存入辅助变量temp中,让temp逐个与A[m],A[m1],...,A[1]进行比较,当temp<A[j](1≤j≤m)时,将A[j]后移一位,否则将temp存入A[j+1]中。重复 上述过程,继续插入A[m+1],A[m+3],...,A[m+n],最终A[]`中元素整体有序。 
void SortArr(int A[],int m,int n) {
	for (int i = m; i < m + n; i++) {
		int temp = A[i];
		for (int j = i - 1; j >= 0; j--) {
			if (temp < A[j]) {
				A[j + 1] = A[j];
			}
			else {
				A[j + 1] = temp;
				break;     //note:不要忘记!!
			}
		}
	}
}

(3) 算法的时间和空间复杂度
时间复杂度为O(mn)
空间复杂度为O(1)

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值