constint MAXLEN=100; // 要求至多存100个元素 int a[110], len; intInsert(int a[], int x, int &len, int ith){ // 将x插入坐标ith,超过表限制长度则报错,并维护表长度 if(len == MAXLEN) { return-1; // 假设-1为报错信号 } for(int i = len; i > ith; i --) { a[i] = a[i - 1]; // 把ith位置之后的元素向后挪 } a[ith] = x; // ith位置已空出,放入x len ++; // 维护元素个数 return0; } intmain(){ len = 0; // 最初没有元素 Insert(a, 3, len, 0); Insert(a, 1, len, 1); Insert(a, 5, len, 2); Insert(a, 8, len, 1); for(int i = 0; i < len; i ++) { printf("%d ", a[i]); } printf("\n"); // 查看输出是否为 3 8 1 5 return0; }
批量删除示例,按左闭右开区间 \([s,
e)\)进行批量删除
下标
0
1
2
3
4
5
6
7
8
数值
12
32
50
17
18
30
27
s
e
插入后
12
32
50
30
27
1 2 3 4 5 6 7 8 9 10 11
constint MAXLEN=100; // 要求至多存100个元素 int a[110], len; intDelRange(int a[], int x, int &len, int s, int e){ // 删除 [s, e) 左闭右开区间内的元素,也就是把 e 之后所有元素平移到 s int i = s, j = min(len, e); for(; j < len; i ++, j ++) { a[i] = j; } len = i; // 平移结束时,i 指向的就是最后一个元素的下一个位置 return0; }
int a[100], length; // 有序 intBiSearch(int num, int a[], int alen){ // left right 标识左闭右开区间 // 即 left 指向首元素,right指向末元素的下一个位置 int left = 0, right = alen; while(left < right - 1) { // left与right的中间位置,这里右移运算与除以2等价 int mid = left + right >> 1; if(a[mid] <= num) left = mid; else right = mid; // right 保持考察区间右侧开区间,这里已排除mid } // left 的位置是搜索结果 return a[left] == num ? left : -1; }
intLowerBound(int a[], int n, int x){ // 在元素个数为 n 的有序数组 a[] 中查找 x 的 Lower Bound int left = 0, right = n, mid; while(left < right) { mid = (left + right) / 2; if(a[mid] >= x) right = mid; else left = mid + 1; } return left == n ? -1 : left; } intUpperBound(int a[], int n, int x){ // 在元素个数为 n 的有序数组 a[] 中查找 x 的 Upper Bound int left = 0, right = n, mid; while(left < right) { mid = (left + right) / 2; if(a[mid] > x) right = mid; else left = mid + 1; } return left == n ? -1 : left; }
二分查找的写法并不唯一,比如前面动图的代码和后面的 Lower Bound
写法就有区别,新手很容易在处理边界时困惑或出错,比如
if(a[mid] > x)还是if(a[mid] >= x)?为什么
right = mid 而 left = mid + 1?循环条件是
left < right 还是 left <= right ?
structNode { int c; // 系数 int e; // 指数 int nex; // 链表下一个节点下标 }; Node lst[9999]; int tp; intNewNode(){ // ... } voidAddTail(int hp, int c, int e){ // TODO } intmain(){ int n, e; tp = 0; int head = NewNode(); scanf("%d", &n); // n项,但指数不保证连续 for(int i = 0; i < n; i ++) { scanf("%d%d", &c, &e); // 输入保证 e 从小到大递增 int p = NewNode(); lst[p].c = c; lst[p].e = e; AddTail(head, c, e); } return0; }
思考:两个这样的多项式相加如何计算和保存结果
提示:因为 e
递增,可以两个游标分别对应两个链表异步对齐前进,新结果插入到新链表中