有关高精度和排序的回顾
注:本文为回顾,所以仅会记录本人认为的难点与分析
高精度
高精度乘法
乘法可用竖式计算,\(a,b\)为因数,\(c\)为积
列出竖式后,可以发现,\(c\)的值与上一位的进位\(x\),\(a_i,b_j\)的积和进行几次计算后\(c\)的值有关,所以我们得到\(c_{i+j-1}=a_i \times b_j + x + c_{i+j-1},x=c_{i+j-1} \div 10,c_{i+j-1} \% =10\);
由此,我们可以得到以下程序:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int lena,lenb,lenc,a[201],b[201],c[40101],x;
char al[201],bl[201];
int main(){
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
scanf("%s",&al);
scanf("%s",&bl);
lena = strlen(al);
lenb = strlen(bl);
for (int i = 0;i <= lena - 1;i ++)
a[lena - i] = al[i] - '0';
for (int i = 0;i <= lenb - 1;i ++)
b[lenb - i] = bl[i] - '0';
for (int i = 1;i <= lena;i ++){
x = 0;
for (int j = 1;j <= lenb;j ++){
c[i + j - 1] = c[i + j - 1] + x + a[i] * b[j];
x = c[i + j - 1] / 10;
c[i + j - 1] %= 10;
}
c[i + lenb] = x;
}
lenc = lena + lenb;
while (c[lenc] == 0 && lenc > 1)
lenc --;
for (int i = lenc;i >= 1;i --)
cout << c[i];
return 0;
}
高精度除法
我们利用减法代替除法,一次次的进行相减,直到无法继续减
比较
这里主要用于两数相减时,比较两者大小,若相等,返回零即可,若被减数\(a\)大于减数\(b\),返回1,继续运算,若小于\(b\),则返回-1,表示已不能继续减;
int compare(int a[],int b[]){
if (a[0] < b[0]) return -1;
if (a[0] > b[0]) return 1;
for (int i = a[0];i > 0;i --){
if (a[i] > b[i]) return 1;
if (b[i] > a[i]) return -1;
}
return 0;
}
相减
先进行判断,是否可以相减,再进行运算,具体步骤与高精度减法类似
void jian(int a[],int b[]){
int f,i;
f = compare(a,b);
if (f == 0){
a[0] = 0;
return;
}
if (f == 1){
for (i = 1;i <= a[0];i ++){
if (a[i] < b[i]){
a[i + 1] --;
a[i] += 10;
}
a[i] -= b[i];
}
while (a[a[0]] == 0 && a[0] > 0) //去除前导零
a[0] --;
}
}
复制
由于我们在运算中并不是对两个高精数直接相减,而是分段进行,所以需要一个复制函数
void copy(int p[],int q[],int num){
for (int i = 1;i <= p[0];i ++)
q[i + num - 1] = p[i]; //复制,可保留相应位数
q[0] = p[0] + num - 1;
}
除法
我们在上面讲过了,除法用减法进行代替,所以这里的本质就是一次次循环相减,每减去一次,相应位上的\(c\)自加一;
void chu(int a[],int b[],int c[]){
int i,tem[101];
c[0] = a[0] - b[0] + 1;
for (i = c[0];i > 0;i --){
memset(tem,0,sizeof(tem));
copy(b,tem,i);//对需减去的数进行复制
while (compare(a,tem) >= 0){
c[i] ++;//每进行一次,c+1
jian(a,tem);//运行减法
}
}
while (c[0] > 0 && c[c[0]] == 0)
c[0] --;//去除前导零
}
完整代码
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int a[101],b[101],c[101];
void init(int i[]){
string s;
cin >> s;
i[0] = s.length();
for (int j = 1;j <= i[0];j ++)
i[j] = s[i[0] - j] - '0';
}
int compare(int a[],int b[]){
if (a[0] < b[0]) return -1;
if (a[0] > b[0]) return 1;
for (int i = a[0];i > 0;i --){
if (a[i] > b[i]) return 1;
if (b[i] > a[i]) return -1;
}
return 0;
}
void jian(int a[],int b[]){
int f,i;
f = compare(a,b);
if (f == 0){
a[0] = 0;
return;
}
if (f == 1){
for (i = 1;i <= a[0];i ++){
if (a[i] < b[i]){
a[i + 1] --;
a[i] += 10;
}
a[i] -= b[i];
}
while (a[a[0]] == 0 && a[0] > 0)
a[0] --;
}
}
void copy(int p[],int q[],int num){
for (int i = 1;i <= p[0];i ++)
q[i + num - 1] = p[i];
q[0] = p[0] + num - 1;
}
void chu(int a[],int b[],int c[]){
int i,tem[101];
c[0] = a[0] - b[0] + 1;
for (i = c[0];i > 0;i --){
memset(tem,0,sizeof(tem));
copy(b,tem,i);
while (compare(a,tem) >= 0){
c[i] ++;
jian(a,tem);
}
}
while (c[0] > 0 && c[c[0]] == 0)
c[0] --;
}
void print(int p[]){
if (p[0] == 0){
cout << 0 << endl;
return;
}
for (int i = p[0];i > 0;i --)
cout << p[i];
cout << endl;
}
int main() {
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
init(a);
init(b);
chu(a,b,c);
print(c);
print(a);
return 0;
}
对应题目
排序
这里主要讲解快速排序
快排的主要思想是二分法,通过对数据进行二分提高速度,时间复杂度为\(O(n\log_{2}{n})\),不过是一种不稳定的排序
#include <iostream>
#include <algorithm>
using namespace std;
void quicksort (int [], int, int);
int partition (int [], int, int);
int main()
{
const int SIZE = 10;
int array[SIZE] = {17, 53, 9, 2, 30, 1, 82, 64, 26, 5};
for (int k = 0; k < SIZE; k++)
cout << array[k] << " ";
cout << endl;
quicksort (array, 0, SIZE-1);
for (int k = 0; k < SIZE; k++)
cout << array[k] << " ";
cout << endl;
return 0;
}
void quicksort (int arr[], int start, int end)
{
if (start < end)
{
int p = partition(arr, start, end);
quicksort(arr, start, p - 1);
quicksort(arr, p + 1, end);
}
}
int partition(int arr[], int start, int end)
{
int pivotValue = arr[start];
int pivotPosition = start;
for (int pos = start + 1; pos <= end; pos++)
{
if (arr[pos] < pivotValue)
{
swap(arr[pivotPosition + 1], arr[pos]);
swap(arr[pivotPosition], arr[pivotPosition + 1]);
pivotPosition ++;
}
}
return pivotPosition;
}
更新日志
- \(2020.5.9\) 完成编辑
日后优化会持续跟进