链式存储的线性表的倒数第m个元素
#include <bits/stdc++.h>
using namespace std;
#define ERROR -1
const int N = 1e3 + 10;
typedef int ElementType;
typedef struct Node *PtrToNode;
struct Node {
ElementType Data;
PtrToNode Next;
}a[N];
typedef PtrToNode List;
ElementType n;
List L;
List Read(){
cin >> n;
for(int i = 1;i <= n;i ++ ){
cin >> a[i].Data;
//if(i != n) a[i].Next = a[i + 1].Next;此时a[i + 1].Next还未被赋值,后面的a[i + 1].Next都会变成NULL
if(i != n) a[i].Next = &a[i + 1];//应该传地址
else a[i].Next = NULL;
}
return &a[1];//返回表头的地址。
}
void Print(){
for(int i = 1;i <= n;i ++ ){
cout << a[i].Data;
if(i != n) a[i].Next = a[i + 1].Next;
else a[i].Next = NULL;
}
}
//思路:右指针先向右移动,找到第m个,此后左右指针同时移动,直到右指针结尾,左指针指向的数据即为倒数第m个.
ElementType Find( List L, ElementType m ){
List l,r;
ElementType num = 0;
l = r = L;
while(r && (++ num ) <= m){//右指针抵达第m个
r = r -> Next;
}
if(num <= m) return ERROR;//m超过了长度
while(r){//开始同时移动
r = r -> Next;
l = l -> Next;
}
ElementType ans = l -> Data;
return ans;
}
ElementType main() {
L = Read();
ElementType m;
cin >> m;
cout << Find(L,m);
puts("");
Print();
return 0;
}
单链表操作(增删改查)
#include<bits/stdc++.h>
using namespace std;
typedef int ElementType;
typedef struct LNode *PtrToLNode;
ElementType n,m,z;
struct LNode{
ElementType Data;
PtrToLNode Next;
};
typedef PtrToLNode List;
#define ERROR NULL
//带头结点的单链表
//求表长
ElementType Length(List PtrL){
List p = PtrL;
int l = 0;
while(p){
p = p -> Next;
l ++ ;
}
return l;
}
//按值查找
int Find_value( List L, ElementType X ){
List p = L; //p指向L的第1个结点
int cnt = 1;
while (p && p->Data != X){//非空且没找到
p = p->Next;
cnt ++ ;
}
cnt -- ;//减去头结点。
if (p)
return cnt;
else
return -1;
}
//按序号查找
int Find_number( List L, ElementType X ){
List p = L; //p指向L的第1个结点
int cnt = 1;//将头结点赋值为0就可以避免 + 1问题。
while (p && cnt != X + 1){//非空且没找到;注意头结点,所以要 + 1
p = p -> Next;
cnt ++ ;
}
if (cnt == X + 1)
return p -> Data;
else
return -1;
}
//在第i个位置后插入元素e(带头结点)
bool Insert(List L, int i, ElementType e){//找到第i-1个结点,将新结点插入其后
if(i < 1) return false;
List p; //指针p指向当前扫描到的结点
int cnt = 0; //当前p指向的是第几个结点
p = L; //L指向头结点,头结点是第0个结点(不存数据)
while (p != ERROR && cnt < i ) { //循环找到第 i 个结点(注意不是 <= )
p = p -> Next;
cnt ++ ;
}
if(p == ERROR) {//i值不合法
cout << "插入错误" << endl;
return false;
}
List s = (List) malloc (sizeof(LNode));
s->Data = e;
s -> Next = p -> Next ;
p -> Next = s; //将结点s连到p之后
return true; //插入成功
}
//删除第i个元素
ElementType Delete ( List L,ElementType i){
if(i <= 0) return 0;
List p = L;
int count = 0;
while(p != ERROR && count < i - 1){
p = p->Next;
count ++ ;
}
if(p == ERROR) {
cout << "删除错误" << endl;
return 0;
}
p -> Next = (p -> Next) -> Next;
return 1;
}
void Read(List L){
int m;
cin >> m;
List p = L;
while(m -- ){
int i;
cin >> i;
List link = (List)malloc(sizeof(struct LNode));
link->Data = i;
link->Next = NULL;
p->Next = link;
p = link;
}
}
void Print(List L){
L = L -> Next;//跳过头结点
while(L != NULL){
cout << L -> Data << " ";
L = L -> Next;
}
}
int main(){
List L = (List)malloc(sizeof(struct LNode));
int t;
Read(L);
cout << "1.求表长" << endl << "2.按值查找" << endl << "3.按序号查找" << endl << "4.在第i个位置插入e" << endl << "5.删除第i个数字" << endl;
while(cin >> t){
switch(t){
case 1:
cout << Length(L) - 1 << endl;//减一是减去头结点。
puts("");
break;
case 2:
ElementType n1;
cin >> n1;
cout << Find_value(L,n1) << endl;
puts("");
break;
case 3:
ElementType n4;
cin >> n4;
cout << Find_number(L,n4) << endl;
puts("");
break;
case 4:
ElementType i,e;
cin >> i >> e;
Insert(L,i,e);
Print(L);
puts("");
puts("");
break;
case 5:
ElementType x3;
cin >> x3;
Delete(L,x3);
Print(L);
puts("");
puts("");
}
}
return 0;
}
3-3 一元多项式的乘法与加法运算
设计函数分别求两个一元多项式的乘积与和。
输入格式:
输入分2行,每行分别先给出多项式非零项的个数,再以指数递降方式输入一个多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。
输出格式:
输出分2行,分别以指数递降方式输出乘积多项式以及和多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。零多项式应输出0 0
。
输入样例:
4 3 4 -5 2 6 1 -2 0
3 5 20 -7 4 3 1
输出样例:
15 24 -25 22 30 21 -10 20 -21 8 35 6 -33 5 14 4 -15 3 18 2 -6 1
5 20 -4 4 -5 2 9 1 -2 0
代码长度限制
16 KB
时间限制
200 ms
内存限制
64 MB
思路:
1.用数组下标储存指数,相对应的数组位置存储这个指数的系数。
2.多项式加法只需将指数相同的系数相加,多项式乘法只需将各项的系数相乘指数相加。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
void Read(int c[]) {
int n;
cin >> n;
while (n -- ) {
int k,x;
cin >> k >> x;
c[x] += k; //指数为x的系数放在x位置上
}
}
void Print(int c[]) {
bool flag = false;//判断零多项式(默认是)
for (int i = N - 1; i >= 0; i--)//指数递减
if (c[i]) {//防止输出多项式非零项的系数
if (flag) cout << " " ;
cout << c[i] << " " << i ;//输出系数和位置(指数)
flag = true;
}
if (!flag) cout << "0 0" << endl;//零多项式
else puts("");
}
void Mul(int mul[], int a[], int b[]) {
for (int i = N - 1; i >= 0; i--)
for (int j = 0; j < N; j++)
mul[i + j] += a[i] * b[j];
}
void Add(int add[], int a[], int b[]) {
for (int i = N - 1; i >= 0; i -- ) add[i] += a[i];
for (int i = N - 1; i >= 0; i--) add[i] += b[i];
}
int main() {
int a[N]{0}, b[N]{0};
int mul[N]{0}, add[N]{0};
Read(a);
Read(b);
Mul(mul, a, b);
Add(add, a, b);
Print(mul);
Print(add);
return 0;
}
喜提18分,后来改了改,发现是nmd数组开小了
#include <bits/stdc++.h>
using namespace std;
const int N = 1e4 + 10;
void Read(int c[]) {
int n;
cin >> n;
while (n -- ) {
int k,x;
cin >> k >> x;
c[x] += k; //指数为x的系数放在x位置上
}
}
void Print(int c[]) {
bool flag = false;//判断零多项式(默认是)
for (int i = N - 1; i >= 0; i--)//指数递减
if (c[i]) {//防止输出多项式非零项的系数
if (flag) cout << " " ;
cout << c[i] << " " << i ;//输出系数和位置(指数)
flag = true;
}
if (!flag) cout << "0 0" << endl;//零多项式
else puts("");
}
void Mul(int mul[], int a[], int b[]) {
for (int i = N - 1; i >= 0; i--)
for (int j = 0; j < N; j++)
mul[i + j] += a[i] * b[j];
}
void Add(int add[], int a[], int b[]) {
for (int i = N - 1; i >= 0; i -- ) add[i] += a[i];
for (int i = N - 1; i >= 0; i--) add[i] += b[i];
}
int main() {
int a[N]{0}, b[N]{0};
int mul[N]{0}, add[N]{0};
Read(a);
Read(b);
Mul(mul, a, b);
Add(add, a, b);
Print(mul);
Print(add);
return 0;
}
3-1 两个有序链表序列的合并
L1
和L2
是给定的带头结点的单链表,其结点存储的数据是递增有序的;函数Merge
要将L1
和L2
合并为一个非递减的整数序列。应直接使用原序列中的结点,返回归并后的带头结点的链表头指针。
输入样例:
3
1 3 5
5
2 4 6 8 10
输出样例:
1 2 3 4 5 6 8 10
NULL
NULL
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
#include <bits/stdc++.h>
using namespace std;
typedef int ElementType;
typedef struct Node *PtrToNode;
struct Node {
ElementType Data;
PtrToNode Next;
};
typedef PtrToNode List;
List Read(){
int n;
cin >> n;
List L = (List)malloc(sizeof(PtrToNode));//申请一个头节点
L->Next = NULL;//先建立一个以L为头结点的空链表
if(n != 0){
List p = L;
for(int i = 0;i < n;i ++ ){
List link = (List)malloc(sizeof(struct Node));
link -> Next = NULL;
cin >> link -> Data;
p -> Next = link;
p = link;//更新
}
p->Next = NULL;//最后别忘NULL.
}
return L;
}
void Print(List L){
List P = L->Next;//跳过头结点
if(P){//p:作为判断。
List r;
r = L;
while(r -> Next){//跳过头结点
r = r -> Next;
cout << r -> Data << " ";
}
}
else cout << "NULL";
puts("");
}
List Merge( List L1, List L2){
List p1,p2,p,L;
L = (List)malloc(sizeof(struct Node));
//p1,p2指向第一个结点
p1 = L1->Next;
p2 = L2->Next;
p = L;// p指向L的头结点
// 当L1 L2 均未到达表尾 依次摘取两表中值较小的结点插入到L最后
while(p1 != NULL && p2 != NULL){
if(p1 -> Data <= p2 -> Data){
p->Next = p1;
//更新
p = p1;
p1 = p1 -> Next;
}
else{
p->Next = p2;
p = p2;
p2 = p2 -> Next;
}
}
//当有一方走到尽头,将另一方赋值给L
p->Next = max(p1,p2);
L1 -> Next = NULL;
L2 -> Next = NULL;
return L;
}
int main(){
List L1, L2, L;
L1 = Read();
L2 = Read();
L = Merge(L1, L2);
Print(L);
Print(L1);
Print(L2);
return 0;
}
3-2 最长连续递增子序列
给定一个顺序存储的线性表,请设计一个算法查找该线性表中最长的连续递增子序列。例如,(1,9,2,5,7,3,4,6,8,0)中最长的递增子序列为(3,4,6,8)。
输入格式:
输入第1行给出正整数n(≤105);第2行给出n个整数,其间以空格分隔。
输出格式:
在一行中输出第一次出现的最长连续递增子序列,数字之间用空格分隔,序列结尾不能有多余空格。
输入样例:
15
1 9 2 5 7 3 4 6 8 0 11 15 17 17 10
输出样例:
3 4 6 8
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
思路:
当前元素与后面的比对,如果后一个元素大于这个元素,那么count++,一旦遇到两两之间不满足递增关系的,则break;count不再计数。
最后对所有元素的count进行比较,找出最大的,从这个最大的元素开始往后输出相应count数个元素,即满足题目的要求。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
struct node{
int data;
int count;
}s[N];
int main(){
ios::sync_with_stdio(false);
int n;
cin >> n;
for(int i = 1;i <= n;i ++ ){
cin >> s[i].data;
s[i].count = 1;
}
for(int i = 1;i <= n - 1;i ++ ){
for(int j = i + 1;j <= n;j ++ ){
if(s[j].data > s[j-1].data) s[i].count ++ ;
else break;
}
}
int cnt = 0,pos;
for(int i = 1;i <= n;i ++ ){
if(cnt < s[i].count){
cnt = s[i].count;
pos = i;
}
}
for(int i = pos;i <= (cnt - 1 + pos) - 1;i ++ )
cout << s[i].data << " ";
cout << s[cnt + pos - 1].data;
return 0;
}