【算法导论】2.1~2.3

【算法导论】2.1~2.3

(排序,分治)


插入排序,用文中的列子 整理扑克牌 可以非常清晰地描述该算法。效率为 n² 伪代码如下:

1 for j=2 to A.length
2 key=A[j]
3 i:=j-1
4 while i>0 and A[i]>key
5 A[i+1]=A[i]
6 i=i-1
7 a[i+1]=k

代码如下

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
	int n, i, j, k, a[30000];
	scanf("%d", &n);
	for (i = 1; i <= n; i++)
		scanf("%d", &a[i]);
	for (j = 2; j <= n; j++)
	{
		k = a[j];
		i = j - 1;
		while (i > 0 && a[i] > k)
		{
			a[i + 1] = a[i];
			i--;
		}
		a[i + 1] = k;
	}
	for (i = 1; i <= n; i++)
		printf("%d ", a[i]);
	getchar();
	getchar();
	return 0;
}

选择排序:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
	int n, i, j, k, t, a[30000];
	scanf("%d", &n);
	for (i = 1; i <= n; i++)
		scanf("%d", &a[i]);
	for (i = 1; i <= n; i++)
	{
		a[0] = 3200;
		for (j = i; j <= n; j++)
		{
			if (a[j] < a[0])
			{
				k = j;
				a[0] = a[j];
			}
		}
		t = a[i];
		a[i] = a[k];
		a[k] = t;
	}
	for (i = 1; i<= n; i++)
		printf("%d ", a[i]);
	getchar();
	getchar();
	return 0;
}

归并排序

#define _CRT_SECURE_NO_WARNINGS
#define MAXN 3200
#include<stdio.h>
void merge(int a[], int p, int m, int q)
{
	int i, j, t, L[3200], R[3200];
	int n1 = m - p + 1, n2 = q - m;
	for (i = p; i <= m; i++)
		L[i - p + 1] = a[i];
	for (i = m + 1; i <= q; i++)
		R[i - m] = a[i];
	L[n1 + 1] = R[n2 + 1] = MAXN;
	i = j = 1;
	for (t = p; t <= q; t++)
	{
		if (L[i] <= R[j])
		{
			a[t] = L[i];
			i++;
		}
		else
		{
			a[t] = R[j];
			j++;
		}
	}
}
void merge_sort(int a[], int p, int q)
{
	int m = (p + q) / 2;
	if (q == p) return;
	merge_sort(a, p, m);
	merge_sort(a, m + 1, q);
	merge(a, p, m, q);
	return;
}
int main()
{
	int n, i, j, k, t, a[30000];
	scanf("%d", &n);
	for (i = 1; i <= n; i++)
		scanf("%d", &a[i]);
	merge_sort(a, 1, n);
	for (i = 1; i <= n; i++)
		printf("%d ", a[i]);
	getchar();
	getchar();
	return 0;
}

冒泡排序

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
	int n, i, j, t, a[30000];
	scanf("%d", &n);
	for (i = 1; i <= n; i++)
		scanf("%d", &a[i]);
	for (i = 1; i <= n; i++)
	{
		for(j = n; j > i; j--)
			if (a[j] < a[j - 1])
			{
				t = a[j];
				a[j] = a[j - 1];
				a[j - 1] = t;
			}
	}
	for (i = 1; i <= n; i++)
		printf("%d ", a[i]);
	getchar();
	getchar();
	return 0;
}

霍纳规则

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<time.h>
double fun_1(double a[], int n, double x)
{
	int i, j;
	double t, ans = 0;
	for (i = 0; i <= n; i++)
	{
		t = 1;
		for (j = 1; j <= i; j++)
			t *= x;
		ans += a[i] * t;
	}
	return ans;
}
double fun_2(double a[], int n, double x)
{
	int i;
	double y = 0;
	for (i = n; i >= 0; i--)
		y = a[i] + x*y;
	return y;
}
int main()
{
	double a[3200], x, ans;
	int n, t, i;
	clock_t st, ed;
	scanf("%d", &n);
	for (i = 0; i <= n; i++)
		scanf("%lf", &a[i]);
	scanf("%d", &t);
	while (t > 0)
	{
		t--;
		scanf("%lf", &x);
		st = clock();
		ans = fun_1(a,n,x);
		ed = clock();
		printf("%6.5f  %ld\n", ans, ed-st);
		st = clock();
		ans = fun_2(a, n, x);
		ed = clock();
		printf("%6.5f  %ld\n", ans, ed-st);
	}
	getchar();
	getchar();
}

求序列的逆序对数

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int ans = 0;
void merge(int a[], int p, int m, int q)
{
	int i, j, t, L[3200], R[3200];
	int n1 = m - p + 1, n2 = q - m;
	for (i = p; i <= m; i++)
		L[i - p + 1] = a[i];
	for (i = m + 1; i <= q; i++)
		R[i - m] = a[i];
	L[n1 + 1] = R[n2 + 1] = 3200;
	i = j = 1;
	for (t = p; t <= q; t++)
	{
		if (L[i] <= R[j])
		{
			a[t] = L[i];
			i++;
		}
		else
		{
			a[t] = R[j];
			j++;
			ans += n1 - i + 1;
		}
	}
}
void cal(int a[], int p, int q)
{
	int i, j, m = (p + q) / 2;
	if (p == q) return;
	cal(a, p, m);
	cal(a, m + 1, q);
	merge(a, p, m, q);
}
int main()
{
	int a[3200], n, i, j;
	scanf("%d", &n);
	for (i = 1; i <= n; i++)
		scanf("%d", &a[i]);
	cal(a, 1, n);
	printf("%d\n", ans);
	getchar();
	getchar();
}

下面的解释不错:

逆序对数实质就是插入排序过程中要移动元素的次数。
归并的时候 前后两个序列都是有序的,可以把这个过程想象成插入排序,将第二个序列的内容插入到第一个有序的序列中。那么插入第二个序列中的元素时,要移动的元素的位数即第一个序列中还未插入到新序列中的元素的个数。即:distance(iL,mid)distance(iL,mid).
作者:楚兴
来源:CSDN
原文:https://blog.csdn.net/foreverling/article/details/46715161
版权声明:本文为博主原创文章,转载请附上博文链接!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值