课本上的板子
(真的全都不会,怎么办
哎 又要考试辽
一、线性表 栈 队列
1.线性表
线性表是逻辑层面上的线性,是元素的有限序列
(1)顺序表实现
template <class E>
class Alist{
private:
int maxSize;
int listSize;
int fence;
E* listArray;
public:
Alist(int size=5000){
maxSize=size;
listSize=fence=0;
listArray = new E[maxSize];
}
~Alist(){
delete [] listArray;
}
void clear(){
delete [] listArray;
listSize= fence = 0;
listArray = new E[maxSize];
}
bool insert(const E& it){
listSize++;
for(int i=fence+1;i<=listSize;i++){
listArray[i]=listArray[i-1];
}
listArray[fence]=it;
}
bool append(const E& it){
listArray[++listSize]=it;
}
bool remove(E&){
for(int i=fence;i<listSize;i++){
listArray[i]=listArray[i+1];
}
delete listArray[listSize--];
}
void setStart(){
fence = 0;
};
void setEnd(){
fence = listSize;
};
void prev(){
fence = fence-1>=0?fence-1:0;
};
void next(){
fence = fence+1<=listSize?fence+1:listSize;
};
int leftLength(){
return fence;
}
int rightLength(){
return listSize-fence;
}
bool setPos(int pos){
if(pos>=0 && pos<=listSize) fence=pos;
return pos>=0 && pos<=listSize;
}
bool getValue(E &it) const{
it = listArray[fence];
return true;
}
void print() const{
int tmp=0;
while(tmp<fence) cout<<listArray[tmp++]<<" ";
cout<<" | ";
while(tmp<listSize) cout<<listArray[tmp++]<<" ";
cout<<endl;
}
};
(2)链表
template <typename E>
class Link{
public:
E ele;
Link* nxt;
Link(const E& e,Link* nxtval=NULL){
ele = e;
nxt=nxtval;
}
Link(Link* nxtval=NULL){
nxt=nxtval;
}
};
template <typename E>
class Llist{
private:
Link<E>* head;
Link<E>* tail;
Link<E>* fence;
int leftcnt;
int rightcnt;
void ini(){
fence = tail = head = new Link<E>;
leftcnt=rightcnt=0;
}
void removeall(){
while(head!=NULL){
fence=head;
head=head->nxt;
delete fence;
}
}
public:
Llist(){
ini();
};
~Llist(){
removeall();
}
void clear(){
removeall();
ini();
}
bool insert(const E& it){
fence->nxt = new Link<E>(it,fence->nxt);
}
bool append(const E& it){
tail->nxt = new Link<E>(it);
}
bool remove(const E& it){
if(fence->nxt==NULL) return 0;
it = fence->nxt->ele;
Link<E>* tmp=fence->nxt;
fence->nxt=tmp->nxt;
//details
if(tail==tmp) tail=fence;
delete tmp;
//details
rightcnt--;
return 1;
}
void serStart(){
fence = head;
rightcnt += leftcnt;
leftcnt=0;
}
void setEnd(){
fence = tail;
leftcnt+=rightcnt;
rightcnt=0;
}
void prev(){
if(fence==head) return;
Link<E>*tmp=head;
while(tmp->nxt!=fence){
tmp=tmp->nxt;
}
fence=tmp;
leftcnt--;
rightcnt++;
}
void next(){
if(fence!=tail){
fence=fence->nxt;
rightcnt--;
leftcnt++;
}
}
int leftLength(){
return leftcnt;
}
int rightLength(){
return rightcnt;
}
bool setPos(int pos){
if(pos<0||pos>rightcnt+leftcnt){
return 0;
}
fence=head;
for(int i=0;i<pos;i++){
fence=fence->nxt;
}
return 1;
}
bool getValue(E& it){
if(rightcnt==0) return 0;
it = fence->nxt->ele;
return 1;
}
void print(){
Link<E>* tmp=head;
while(tmp!=tail){
cout<<tmp->ele<<" ";
tmp=tmp->nxt;
}
cout<<tail->nxt<<endl;
}
};
2.栈
先进后出,这种短短的代码就比较令人愉悦
(1)顺式栈
//顺式栈
template<typename E>
class AStack{
private:
int size;
int top;
E* listarray;
public:
AStack(int s=10){
size=s;
top=0;
listarray = new E[size];
}
~AStack(){
delete []listarray;
}
void clear(){
top=0;
}
bool push(const E&it){
if(top==size) return 0;
listarray[size++]=it;
return 1;
}
bool pop(E& it){
if(top==0) return 0;
it =listarray[--top];
return 1;
}
bool topValue(E& it) const{
if(top==0) return 0;
it=listarray[top-1];
return 1;
}
int length()const{
return top;
}
};
(2)链式栈
//链式栈
template<typename E>
class LStack{
private:
int size;
Link<E>* top;
public:
LStack(int s=10){
size=s;
top=NULL;
};
~LStack(){
clear();
};
void clear(){
while(top!=NULL){
Link<E>* tmp=top;
top=top->nxt;
size=0;
delete top;
}
}
bool push(const E& it){
size++;
top = new Link<E>(it,top);
return 1;
}
bool pop(E& it){
if(size==0) return 0;
Link<E>* tmp=top->nxt;
delete top;
top=tmp;
size--;
return 1;
}
bool topValue(E& it){
if(size==0) return 0;
it = top->ele;
return 1;
}
int length() const{
return size;
}
};
3.队列
先进先出
昨天堕落完躺在床上又开始忏悔了呢(所以这就是我看漫画的理由吗
(不是)
线性实现
取模完了计算个数 下标的时候都要注意
//队列
template<typename E>
class AQueue{
private:
int size;
int front;
int rear;
E* listarray;
public:
AQueue(int s=100){
size=s+1;
rear=0;
front=1;
listarray = new E[size];
}
~AQueue(){
delete []listarray;
}
void clear(){
front=rear;
}
bool enqueue(const E& it){
//如果装不下新的元素
if((rear+2)%size==front) return 0;
rear=(rear+1)%size;
listarray[rear]=it;
return 1;
}
bool dequeue(E& it){
if(length()==0) return 0;
it = listarray[front];
front=(front+1)%size;
return 1;
}
bool frontValue(E& it){
if(length()==0) return 0;
it = listarray[front];
return 1;
}
virtual int length()const{
return ((rear+size)-front+1)%size;
}
};
链表实现
//链式队列
template<typename E>
class LQueue{
private:
Link<E>* front;
Link<E>* rear;
int size;
public:
LQueue(int s=1000){
size=s+1;
front=rear=NULL;
}
~LQueue(){
clear();
}
void clear(){
while(front!=NULL){
Link<E>* tmp=front;
front=front->nxt;
delete tmp;
}
rear=NULL;
size=0;
}
bool enqueue(const E& it){
if(rear==NULL)
front = rear = new Link<E>(it,NULL);
else{
rear->nxt = new Link<E>(it,NULL);
rear=rear->nxt;
}
size++;
return 1;
}
bool dequeue(E& it){
if(length()==0) return 0;
Link<E>* tmp=front;
it = front->ele;
front = front->nxt;
delete tmp;
if(front=NULL) rear=NULL;
size--;
return 1;
}
bool frontValue(E& it){
if(length()==0) return 0;
it=front->ele;
return 1;
}
virtual int length()const{
return size;
}
};
二、内排序
1.O(n^2)插入、冒泡、选择
int b[30];
int n=10;
int a[30]={0,4,2,1,94,2,343,54,233,5};
void print(int c[]){
for(int i=1;i<=n;i++){
cout<<c[i]<<" ";
}
cout<<endl;
}
void ini(){
for(int i=1;i<=n;i++){
b[i]=a[i];
}
}
插入:两层for循环,内层与相邻元素比较
void InsertionSort(){
ini();
for(int i=1;i<=n;i++){
for(int j=i;j>=0;j--){
//!
if(b[j]<b[j-1]){
swap(b[j-1],b[j]);
}
}
}
print(b);
}
冒泡:两层for循环,内层与外层比较
void BubbleSort(){
ini();
for(int i=1;i<=n;i++){
for(int j=i;j<=n;j++){
if(b[i]>b[j]){
swap(b[i],b[j]);
}
}
}
print(b);
}
选择排序:按序选择,不断更新
void InsertionSort(){
ini();
for(int i=1;i<=n;i++){
for(int j=i;j>=0;j--){
//!
if(b[j]<b[j-1]){
swap(b[j-1],b[j]);
}
}
}
print(b);
}
2.O(n^1.5)希尔
这个真的挺秀的,优化的力量
void inssort2(int b[],int n,int incr){
for(int i=incr;i<=n;i+=incr){
for(int j=i;j>incr;j-=incr){
if(b[j]<b[j-incr])
swap(b[j],b[j-incr]);
}
}
}
void ShellSort(){
ini();
for(int i=n/2;i>1;i/=2){
for(int j=1;j<=i;j++){
inssort2(&b[j],n-j,i);
}
}
inssort2(b,n,1);
print(b);
}
3.O(nlogn)归并、快排
归并也有个优化,是在数据范围小的时候用插入排序
以后序号还是从0开始吧,不然老是会出现神秘的bug
void inssort2(int b[],int n,int incr){
for(int i=incr;i<=n;i+=incr){
for(int j=i;j>incr;j-=incr){
if(b[j]<b[j-incr])
swap(b[j],b[j-incr]);
}
}
}
//Merge
int tmp[5000];
void MergeSort(int b[],int tmp[],int l,int r){
if(l==r) return;
int mid=(l+r)>>1;
MergeSort(b,tmp,l,mid);
MergeSort(b,tmp,mid+1,r);
for(int i=l;i<=r;i++){
tmp[i]=b[i];
}
int i=l,j=mid+1;
for(int cur=l;cur<=r;cur++){
//左边到头了
if(i==mid+1){
b[cur]=tmp[j++];
}
//右边用完了
//注意这里是大于,大于!
else if(j>r){
b[cur]=tmp[i++];
}
else if(tmp[i]>tmp[j]){
b[cur]=tmp[j++];
}
else b[cur]=tmp[i++];
}
}
//MergeSort优化版
const int THRESHOLD = 1;
void MergeSort2(int b[],int tmp[],int l,int r){
//小范围数据使用插入排序
if((r-l)<=THRESHOLD){
inssort2(&b[l-1],r-l+1,1);
return;
}
if(l==r) return ;
int i,j,k,mid = (l+r)>>1;
MergeSort2(b,tmp,l,mid);
MergeSort2(b,tmp,mid+1,r);
for(i=mid;i>=l;i--){
tmp[i]=b[i];
}
for(j=1;j<=r-mid;j++){
tmp[r-j+1]=b[j+mid];
}
for(i=l,j=r,k=l;k<=r;k++){
if(tmp[i]>tmp[j]){
b[k]=tmp[j--];
}
else b[k]=tmp[i++];
}
}
快排
写了半天还是错的 我晕了
下面的是错的 先记录一下5555555
//QuickSort
int findpivot(int b[],int l,int r){
return b[(l+r)>>1];
}
int partition(int b[],int l,int r,int pivotval){
do{
while(l<r && b[++l]<pivotval);
while(l<r && b[--r]>pivotval);
swap(b[l],b[r]);
}
while(l<r);
return l;
}
void QuickSort(int b[],int l,int r){
if(r<=l) return ;
int pivot=findpivot(b,l,r);
swap(b[pivot],b[r]);
int k=partition(b,l,r,b[r]);
swap(b[k],b[r]);
QuickSort(b,l,k-1);
QuickSort(b,k+1,r);
}
三、外排序
好像敲不出板子
略过先
插播一个玄妙的字符串哈希函数
//M为哈希表容量
const int M = 101;
int cal(char * key){
unsigned int *lkey = (unsigned int *)key;
int intlength=strlen(key)/4;
unsigned int sum=0;
for(int i=0;i<intlength;i++){
sum+=lkey[i];
}
int ex = strlen(key)-4*intlength;
char tmp[4];
lkey=(unsigned int *)tmp;
lkey[0]=0;
for(int i=0;i<ex;i++){
tmp[i]=key[intlength*4+i];
}
sum+=lkey[0];
return sum%M;
}
四、课本上的图论算法
1.最短路算法
Dijkstra
//Dijkstra算法
//不停的找出最小的边所对应的结点,用这个节点去缩短其他的边
int dis[101];
for(int i=1;i<=n;i++){
dis[i]= city[1][i];
}
book[1] =1;
for(int i=1;i<=n-1;i++){//?
int min = inf;
int t;
for(int j=1;j<=n;j++){
if(book[j]==0&& dis[j]<min){
min = dis[j];
t = j;//存储最小路径序号,因为j会变化
}
}
book[t] =1;
for(int v = 1;v<=n;v++){
if(city[t][v]!= inf){
if(dis[v]>dis[t]+city[t][v])
{
dis[v] = dis[t]+city[t][v];
}
}
}
}
cout<<dis[n];
}
这是中缀表达式-》后缀表达式
相关操作
包括创建后缀表达式(栈+递归)
求解后缀表达式(栈+递归)
感谢英俊潇洒的队友提供的参考 orz
//JadeQ
//杭电 AC 代码 2020.4
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#include<iomanip>
#define INF 0x3f3f3f3f
#define sz sizeof
#define mk make_pair
#define ll long long
using namespace std;
const int maxn = 1e3 + 5;
double ans = 0;
int cnt = 0;
char s[maxn];
string ss, tmp[maxn];
stack <char> in;
stack<string> out;
void pre(char *s) {
int len = 0;
for (int i = 0;i < strlen(s);i++) {
if (s[i] != ' ') {
ss += s[i];
}
}
}
bool isop(char x) {
return x == '+' || x == '-' || x == '*' || x == '/';
}
bool isop(string x) {
return isop(x[0]);
}
double deal(string x) {
double res = 0;
for (int i = 0;i < x.length();i++) {
res *= 10;
res += x[i] - '0';
}
return res;
}
double cal(double a, double b, char op) {
if (op == '+') return double(b + a);
if (op == '-') return double(b - a);
if (op == '*') return double(b * a);
if (op == '/') return double(b / (1.00* a));
}
string tostring(char x) {
string tmp = "";
tmp += x;
return tmp;
}
bool bigger(char a, char b) {
if ((b == '+' || b == '-') && (a == '*' || a == '/')) return 1;
return 0;
}
int t = 0;
//逆波兰式的递归求解
double cal() {
if (isop(tmp[++t])) {
if (tmp[t] == "+") return cal() + cal();
if (tmp[t] == "-") {
double t1 = cal(), t2 = cal();
return t2-t1;
}
if (tmp[t] == "*") return cal()*cal();
if (tmp[t] == "/") {
double t1 = cal(), t2 = cal();
return t2 / t1;
}
}
else return deal(tmp[t]);
}
//用栈模拟计算ans
double use_stack() {
stack<double> num;
for (int i = cnt;i >= 1;i--) {
//cout << tmp[i];
if (!isop(tmp[i])) num.push(deal(tmp[i]));
else {
double a = num.top();num.pop();
double b = num.top();num.pop();
num.push(cal(a, b, tmp[i][0]));
}
}
return num.top();
}
int main() {
ios::sync_with_stdio(false); cin.tie(0);
//生成逆波兰式 -- (栈模拟,递归方法详见另一个cpp文件以及代码解释)
while (cin.getline(s, maxn) && strlen(s) >= 1) {
while (!in.empty()) in.pop();
while (!out.empty()) out.pop();
if (s[0] == '0' && strlen(s) == 1) break;
ss = ""; ans = 0; pre(s); cnt = 0;t = 0;
int last = 0;
for (int i = 0;i < ss.length();i++) {
if (isop(ss[i])) {
out.push(ss.substr(last, i - last));
last = i + 1;
if (!in.empty() && !bigger(ss[i], in.top())) {
while (!in.empty() && !bigger(ss[i], in.top())) {
out.push(tostring(in.top()));
in.pop();
}
}
in.push(ss[i]);
}
else if (i == ss.length() - 1)
out.push(ss.substr(last, i - last + 1));
}
while (!in.empty()) {
out.push(tostring(in.top()));in.pop();
}
while (!out.empty()) {
tmp[++cnt] = out.top();
out.pop();
}
//(1)
//用栈模拟计算ans
//ans = use_stack();
//(2)
ans = cal();
//也可以用递归求解逆波兰式
//cout << endl;
printf("%.2lf\n", ans);
}
return 0;
}
//qqq
//#include "pch.h"
//JadeQ 2020.4
//直接输出后缀表达式的程序
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#include<iomanip>
#define INF 0x3f3f3f3f
#define sz sizeof
#define mk make_pair
#define ll long long
using namespace std;
const int maxn = 1e3 + 5;
double ans = 0;
int cnt = 0,t = 0;
char s[maxn];
string tmp[maxn];
map<char, int> mp;
//预处理 去空格
string pre(char *s) {
string ss = "";
int len = 0;
for (int i = 0;i < strlen(s);i++) {
if (s[i] != ' ') {
ss += s[i];
}
}
return ss;
}
bool isop(char x) {
return x == '+' || x == '-' || x == '*' || x == '/';
}
bool isop(string x) {
return isop(x[0]);
}
bool isnum(string x) {
for (int i = 0;i < x.length();i++)
if (!(x[i] >= '0' && x[i] <= '9')) return 0;
return 1;
}
//string->double
double deal(string x) {
double res = 0;
for (int i = 0;i < x.length();i++) {
res *= 10;
res += x[i] - '0';
}
return res;
}
//递归求解后缀表达式
double cal() {
if (isop(tmp[++t])) {
if (tmp[t] == "+") return cal() + cal();
if (tmp[t] == "-") {
double t1 = cal(), t2 = cal();
return t2 - t1;
}
if (tmp[t] == "*") return cal()*cal();
if (tmp[t] == "/") {
double t1 = cal(), t2 = cal();
return t2 / t1;
}
}
else return deal(tmp[t]);
}
//生成逆波兰表达式--递归
string solve(string ss, int L, int R) {
if (R >= L && isnum(ss.substr(L, R - L + 1))) return ss.substr(L, R - L + 1);
int pos = 0; char cur_op = ' ';
for (int i = L;i <= R;i++) {
if (isop(ss[i]) && mp[cur_op] >= mp[ss[i]]) {
cur_op = ss[i];pos = i;
}
}
return solve(ss, L, pos - 1) + " " + solve(ss, pos + 1, R) + " " + cur_op;
}
//复制生成的逆波兰表达式到目标字符串数组tmp(求解用)
void copy(string tmp[],string ttmp) {
int st = 0, ed = 0;
for (int i = 0;i < ttmp.length();i++) {
if (i == ttmp.length() - 1) {
ed = i;
tmp[++cnt] = ttmp.substr(st, ed - st + 1);
}
if (ttmp[i] == ' ') {
ed = i - 1;
tmp[++cnt] = ttmp.substr(st, ed - st + 1);
st = i + 1;
}
}
for (int i = 1;i <= cnt / 2;i++) swap(tmp[i], tmp[cnt - i + 1]);
}
void ini() {
ans = 0;
mp[' '] = 3;mp['+'] = mp['-'] = 1; mp['*'] = mp['/'] = 2;
cnt = 0;t = 0;
}
int main() {
ios::sync_with_stdio(false);cin.tie(0);
while (cin.getline(s, maxn) && strlen(s) >= 1) {
if (s[0] == '0' && strlen(s) == 1) break;
ini();
string ss = pre(s);
copy(tmp, solve(ss, 0, ss.length() - 1));
ans = cal();
printf("%.2lf\n", ans);
//若要查看生成的逆波兰表达式,去钓掉下行注释
//cout << solve(ss,0,ss.length()-1) << endl;
}
return 0;
}
//#include"pch.h"
//JadeQ
//增加处理括号的情况 2020.4
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#include<iomanip>
#define INF 0x3f3f3f3f
#define sz sizeof
#define mk make_pair
#define ll long long
using namespace std;
const int maxn = 1e3 + 5;
int cnt = 0;
char s[maxn];
string ss, tmp[maxn];
stack <char> in;
stack<string> out;
void pre(char *s) {
for (int i = 0;i < strlen(s);i++)
if (s[i] != ' ') ss += s[i];
}
bool isop(char x) {return x == '+' || x == '-' || x == '*' || x == '/';}
bool isnum(char x) {return x >= '0'&&x <= '9';}
bool bigger(char a, char b) {
if ((b == '+' || b == '-') && (a == '*' || a == '/')) return 1;
return 0;
}
int main() {
ios::sync_with_stdio(false); cin.tie(0);
//生成逆波兰式 -- (栈模拟,递归方法详见另一个cpp文件以及代码解释)
while (cin.getline(s, maxn) && strlen(s) >= 1) {
while (!in.empty()) in.pop();
while (!out.empty()) out.pop();
if (s[0] == '0' && strlen(s) == 1) break;
ss = ""; pre(s); cnt = 0;
for (int i = 0;i < ss.length();i++) {
if (isnum(ss[i])) {
int ed = i, st = i;
while (isnum(ss[ed])) ed++;
out.push(ss.substr(st, ed - st));
i = ed - 1;
}
else if (ss[i] == '(') in.push(ss[i]);
else if (isop(ss[i])) {
while (!in.empty() && !bigger(ss[i], in.top())&& in.top()!='(') {
out.push(""+in.top());
in.pop();
}
in.push(ss[i]);
}
else if (ss[i] == ')') {
while (in.top() != '(') {
out.push(""+in.top());in.pop();
}
in.pop();
}
}
while (!in.empty()) {
out.push(""+in.top());
in.pop();
}
while (!out.empty()) {
tmp[++cnt] = out.top();
out.pop();
}
for (int i = cnt;i >= 1;i--) {
cout << tmp[i]<<" ";
}
cout << endl;
}
return 0;
}
真正的码其实很少,都是乱七八糟的处理过程
完事了,舒服