【算法导论】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
版权声明:本文为博主原创文章,转载请附上博文链接!