数据结构笔记(一)——代码开题

个人学习笔记,不喜勿喷。

1、空间使用:printN函数的实现。

#include "stdafx.h"

void printN(int n)
{
	for (int i = 1; i <= n; ++i)
	{
		printf("%d\n", i);
	}
}
void printN(int n)
{
	if (n>=1)
	{
		printN(n - 1);
		printf("%d\n", n);
	}
	
}
int _tmain(int argc, _TCHAR* argv[])
{
	printN(10000);
	return 0;
}

递归调用在每一次递归时需要将前一个函数调用的状态保存,输出1~10000时,在输出1之前存储了9999个函数的状态,空间不足爆掉了。

2、算法效率:计算多项式的值

       多项式:  

秦九韶算法:


#include "stdafx.h"
#include<math.h>
#include<time.h>
#define MAXN 10//多项式的项数
#define MAXK 10000//重复计算次数
double f1(int n, double a[], double x)
{
	double ret = a[0];
	for (int i = 1; i <= n;++i)
	{
		ret += a[i] * pow(x, i);
	}
	return ret;
}
//秦九韶算法
double f2(int n, double a[], double x)
{
	double ret = a[n];
	for (int i = n; i > 0;--i)
	{
		ret = a[i - 1] + ret*x;
	}
	return ret;
}
int _tmain(int argc, _TCHAR* argv[])
{
	clock_t start, stop;
	double duration;
	double a[MAXN];
	double ret;

	for (int i = 0; i < MAXN;++i)
	{
		a[i] = (double)i;
	}

	start = clock();
	for (int i = 0; i < MAXK; ++i)
	{
		ret = f1(MAXN, a, 1.01);
	}
	stop = clock();
	duration = (double)(stop - start) / CLK_TCK / MAXK;
	printf("duration1=%6.2e\n", duration);//控制格式,输出最小宽度为6,精度为2,e为以指数形式输出

	start = clock();
	for (int i = 0; i < MAXK; ++i)
	{
		ret = f2(MAXN, a, 1.01);
	}
	stop = clock();
	duration = (double)(stop - start) / CLK_TCK / MAXK;
	printf("duration2=%6.2e\n", duration);

	return 0;
}

3、最大子列和

#include "stdafx.h"
#include<time.h>
#define MAXK 10000//重复计算次数
int maxSubseqSum1(int a[], int n)
{
	int max_sum = 0, this_sum;
	for (int i = 0; i < n;++i)
	{
		for (int j = i; j < n;++j)
		{
			this_sum = 0;
			for (int k = i; k <= j;++k)
			{
				this_sum += a[k];
			}
			if (this_sum>max_sum)
			{
				max_sum = this_sum;
			}
		}
	}
	return max_sum;
}
//暴力解法,求出所有子列和,时间复杂度O(N^2)
int maxSubseqSum2(int a[], int n)
{
	int max_sum = 0, this_sum;
	for (int i = 0; i < n;++i)
	{
		this_sum = 0;
		for (int j = i; j < n;++j)
		{
			this_sum += a[j];
			if (this_sum>max_sum)
			{
				max_sum = this_sum;
			}
		}
	}
	return max_sum;
}
//求三数最大值
int Max3(int a, int b, int c)
{
	return a>b ? (a > c ? a : c) : (b > c ? b : c);
}
//分治思想求解,二分数列,求左右最大子列(递归)和及中间子列和,进行比较
int DivideAndConquer(int list[], int left, int right)
{
	int max_left = 0, max_right = 0;//左右子列最大和
	int max_leftbor = 0, max_rightbor = 0;//中心边界左右两边最大子列和
	int leftbor = 0, rightbor = 0;
	//递归终止条件
	if (left==right)
	{
		if (list[left]>0)
		{
			return list[left];
		}
		else
		{
			return 0;
		}
	}
	int center = (left + right) / 2;
	//递归计算左右两边最大子列和
	max_left = DivideAndConquer(list, left, center);
	max_right = DivideAndConquer(list, center + 1, right);
	//计算中心边界左右两边的最大子列和
	for (int i = center; i >= left;--i)
	{
		leftbor += list[i];
		if (leftbor>max_leftbor)
		{
			max_leftbor = leftbor;
		}
	}
	for (int i = center+1; i <= right;++i)
	{
		rightbor += list[i];
		if (rightbor>max_rightbor)
		{
			max_rightbor = rightbor;
		}
	}
	return Max3(max_left, max_right, max_leftbor + max_rightbor);
}
//保持函数形参的一致,时间复杂度O(NlogN),递归要考虑空间复杂度
int maxSubseqSum3(int a[], int n)
{
	return DivideAndConquer(a, 0, n - 1);
}
//在线处理,一直向右累加,如果比最大值大就更新最大值,如果小于0,则重新开始累加,时间复杂度O(N)
int maxSubseqSum4(int a[], int n)
{
	int max_sum = 0, this_sum = 0;
	for (int i = 0; i < n;++i)
	{
		this_sum += a[i];
		if (this_sum<0)
		{
			this_sum = 0;
		}
		if (this_sum > max_sum)
		{
			max_sum = this_sum;
		}
	}
	return max_sum;
}
//计算函数运行耗时
void computeTime(int(*pf)(int a[], int n))
{
	clock_t start, stop;
	double duration;
	int arr[10] = { 3, -1, 5, 7, -9, 5, 2, 1, -2, 4 };
	int ret;
	start = clock();
	for (int i = 0; i < MAXK; ++i)
	{
		ret = (*pf)(arr, 10);
	}
	stop = clock();
	duration = (double)(stop - start) / CLK_TCK / MAXK;
	printf("duration=%6.2e\n", duration);//控制格式,输出最小宽度为6,精度为2,e为以指数形式输出
}
int _tmain(int argc, _TCHAR* argv[])
{
	computeTime(maxSubseqSum1);
	computeTime(maxSubseqSum2);
	computeTime(maxSubseqSum3);
	computeTime(maxSubseqSum4);
	return 0;
}

4、对分查找

#include "stdafx.h"
#include<iostream>
#define MAXSIZE 10
#define NotFound 0
typedef int ElementType;
using namespace std;
typedef int Position;
typedef struct LNode *List;
struct LNode {
	ElementType Data[MAXSIZE];
	Position Last; /* 保存线性表中最后一个元素的位置 */
};
Position BinarySearch(List L, ElementType X)
{
	Position mid;
	Position low = 1, high = L->Last;
	while (low<=high)
	{
		mid = (high - low) / 2 + low;
		if (X>(L->Data)[mid])
		{
			low = mid + 1;
		}
		else if (X < (L->Data)[mid])
		{
			high = mid - 1;
		}
		else
			return mid;
	}
	return NotFound;
}
int _tmain(int argc, _TCHAR* argv[])
{
	LNode node;
	List L = &node;
	ElementType X;
	Position P;
	int N;
	cin >> N;
	for (int i = 1; i <= N;++i)
	{
		cin>>(L->Data)[i];
	}
	L->Last = N;
	
	cin >> X;
	P = BinarySearch(L, X);
	printf("%d\n", P);
	return 0;
}

5、最大公因子(公约数)

欧几里得算法(辗转相除法)

gcd(a,b)=gcd(b,a mod b):a,b的公约数与b,a mod b的公约数相等。

证明:设a>=b,则a=kb+r,r=a%b

            假设d为a,b的公约数,则d|a,d|b,得d|a-kb,即d|r,d|a%b(|为整除)

            所以d为b与a mod b的公约数。

#include "stdafx.h"
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
//得到input的所有因子并存入rvec中
void getFactor(int input, vector<int>& rvec)
{
	auto n = input;
	for (auto i = 1; i <= n;++i)
	{
		if (input%i == 0)
		{
			rvec.push_back(i);
			rvec.push_back(input / i);
			n = input / i - 1;
		}
	}
}
//得到a与b中最大的相等数,返回该数(a、b升序排列)
int getMaxEqual(vector<int>& a, vector<int>& b)
{
	sort(a.begin(), a.end());
	sort(b.begin(), b.end());
	auto it1 = a.begin();
	auto it2 = b.begin();
	int max_eq;
	bool isFind = false;
	while (it1!=a.end()&&it2!=b.end())
	{
		if (*it1==*it2)
		{
			isFind = true;
			max_eq = *it1;
			++it1, ++it2;
		}
		else if (*it1<*it2)
		{
			++it1;
		}
		else
		{
			++it2;
		}
	}
	if (it1==a.end())
	{
		while (it2!=b.end()&&*it2<=*(a.end()-1))
		{
			if (*it2 == *(a.end() - 1))
			{
				max_eq = *it2;
			}
			++it2;
		}
	}
	else if (it2 ==b.end())
	{
		while (it1 != a.end() && *it1 <= *(b.end() - 1))
		{
			if (*it1 == *(b.end() - 1))
			{
				max_eq = *it1;
			}
			++it1;
		}
	}
	return max_eq;
}
//对较小数遍历,看是否能被大数和小数同时整除
int getCommFactor1(int a, int b)
{
	int n, max_eq = 1,i;
	if (a>b)
	{
		n = b;
	}
	else
	{
		n = a;
	}
	for (i = 1; i <= n;++i)
	{
		if ((a%i==0)&&(b%i==0)&&(i>max_eq))//求余耗时
		{
			max_eq = i;
		}
	}
	return max_eq;
}
//分别计算两数因子,找出因子中的最大相等数
int getCommFactor2(int a, int b)
{
	vector<int> a_fac, b_fac;
	getFactor(a, a_fac);
	getFactor(b, b_fac);
	return getMaxEqual(a_fac, b_fac);
}
//欧几里得算法计算最大公因子
//0除以任何数均为0,0与任何数的最大公约数为这个数
//一直求余,当b=0时,最大公约数就是a
int getCommFactor3(int a, int b)
{
	//异或实现交换两数
	if (a<b)
	{
		a = a^b;//a^b得到a b不同位为1,相同位为0
		b = a^b;//b与a异或,将a中为1对应的位反转,得到原来的b(与1异或反转,与0异或不变)
		a = a^b;//将a(现在为原来的a)变为原来的b
	}
	int temp;
	while (b>0)
	{
		temp = a%b;
		a = b;
		b = temp;
	}
	return a;
}
int _tmain(int argc, _TCHAR* argv[])
{
	int a, b, comm_factor;;
	cin >> a >> b;
	comm_factor = getCommFactor1(a, b);
	cout << "getCommFactor1: " << comm_factor << endl;
	comm_factor = getCommFactor2(a, b);
	cout << "getCommFactor2: " << comm_factor << endl;
	comm_factor = getCommFactor3(a, b);
	cout << "getCommFactor3: " << comm_factor << endl;
	return 0;
}

6、计算一个整数X的N次幂

#include "stdafx.h"
#include<iostream>
using namespace std;
long long powN(long long x, unsigned int n)
{
	if (n==0)
	{
		return 1;
	}
	if (x&1==0)//x为偶数,偶数的最后一位必为0,与1位与得0
	{
		return powN(x*x, n / 2);
	}
	else
	{
		return powN(x*x, n / 2)*x;
	}
}
int _tmain(int argc, _TCHAR* argv[])
{
	long int x;
	unsigned int n;
	cin >> x >> n;
	cout << powN(x, n) << endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/xitie8523/article/details/82993173
今日推荐