数据结构算法类模板代码(基础要闭着眼睛也会写下来)
1.排序(升序排列数列1-N)
1.1插入排序
将无序段的首值保存为temp,使其与有序段比较,插入相应位置,位置后的有序段元素后移。计算复杂度为O(n2)。
int a[maxn], n;
void insertsort() {
for (int i = 2; i <= n; i++) {
int temp = a[i], j = i;
while (j > 1 && temp < a[j - 1]) {
a[j] = a[j - 1];
j--;
}
a[j] = temp;
}
}
1.2快速排序
将数列中的首元素置于左边元素都比它小,右边元素都比它大,那么这个元素肯定在正确的位置,采用递归的方式将所有元素进行此类操作,计算复杂度为O(nlogn)。
int partition(int a[],int left,int right){
int temp=a[left];
while(left<right){
while(left<right&&a[right]>temp)right--;
a[left]=a[right];
while(left<right&&a[left]<=temp)left++;
a[right]=a[left];
}
a[left]=temp;
return left;
}
void quicksort(int a[],int left,int right){
if(left<right){
int pos=partition(a,left,right);
quicksort(a,left,pos-1);
quicksort(a,pos+1,right);
}
}
1.3归并排序
const int maxn=100;
void merge(int A[],int l1,int r1,int l2,int r2){
int i=l1,j=l2;
int temp[maxn],index=0;
while(i<=r1&&j<=r2){
if(A[i]<=A[j])temp[index++]=A[i++];
else temp[index++]=A[j++];
}
while(i<r1)temp[index++]=A[i++];
while(j<r2)temp[index++]=A[j++];
for(i=0;i<index;i++)A[l1+i]=temp[i];
}
void mergesort(int A[],int n){
for(int step=2;step/2<=n;step*=2){
for(int i=1;i<=n;i+=step){
int mid=i+step/2-1;
if(mid+1<=n)merge(A,i,mid,mid+1,min(i+step-1,n));
}
}
}
1.4堆排序
2.图
2.1Dijkstra最短路径
G为图的邻接矩阵,当然这里邻接表形式的dijkstra也需要会。
d为从起点到每个结点的最短距离,n为总结点数,visit用来记录点是否标记。
const int maxn = 10000;
const int INF = 1e9;
int G[maxn][maxn], d[maxn], n;
bool visit[maxn];
void dijkstra(int s) {
fill(visit, visit + maxn, false);
fill(d, d + maxn, INF);
d[s] = 0;
for (int i = 0; i < n; i++) {
int u = -1, MIN = INF;
for (int j = 0; j < n; j++) {
if (!visit[j] && d[j] < MIN) {
u = j;
MIN = d[j];
}
}
if (u == -1)return;
visit[u] = true;
for (int v = 0; v < n; v++)
if (!visit[v] && G[u][v] != INF && d[u] + G[u][v] < d[v])
d[v] = d[u] + G[u][v];
}
}
3.树(讨论二叉树)
struct node {
int data;
node *left,*right;
node(int val) : data(val), left(NULL),right(NULL) {}
};
3.1二叉树的前/中/后/层序遍历
void preorder(node *root) {
if (root == NULL)return;
printf("%d", root->data);
preorder(root->left);
preorder(root->right);
}
void inorder(node *root) {
if (root == NULL)return;
inorder(root->left);
printf("%d", root->data);
inorder(root->right);
}
void postorder(node *root) {
if (root == NULL)return;
postorder(root->left);
postorder(root->right);
printf("%d", root->data);
}
void layerorder(node *root) {
queue<node *> q;
q.push(root);
while (!q.empty()) {
node *top = q.front();
q.pop();
printf("%d", top->data);
if (top->left != NULL)q.push(top->left);
if (top->right != NULL)q.push(top->right);
}
}
3.2二叉查找树
二叉查找树定义为,左节点都小于根结点值,有节点都大于等于根结点值。
void insert(node *&root, int val) {
if (root == NULL) {
root = new node(val);
return;
}
if (val < root->data)insert(root->left, val);
if (val >= root->data)insert(root->right, val);
}
node *creat(int A[], int size) {
node *root = NULL;
for (int i = 0; i < size; i++)
insert(root, A[i]);
return root;
}
3.3.平衡二叉树
平衡二叉树包括计算平衡因子,左旋和右旋,在二叉查找树的基础上对插入点后的树进行了平衡调整。
参考代码:
#include <cstdio>
#include <iostream>
using namespace std;
struct node {
int data, height;
node *left, *right;
node(int val) : data(val), height(1), left(NULL), right(NULL) {}
};
int getheight(node *root) {
if (root == NULL)return 0;
return root->height;
}
void updateheight(node *root) {
root->height = max(getheight(root->left), getheight(root->right)) + 1;
}
int BF(node *root) {
return getheight(root->left) - getheight(root->right);
}
void L(node *&root) {
node *temp = root->right;
root->right = temp->left;
temp->left = root;
updateheight(root);
updateheight(temp);
root = temp;
}
void R(node *&root) {
node *temp = root->left;
root->left = temp->right;
temp->right = root;
updateheight(root);
updateheight(temp);
root = temp;
}
void insert(node *&root, int v) {
if (root == NULL) {
root = new node(v);
return;
}
if (v < root->data) {
insert(root->left, v);
updateheight(root);
if (BF(root) == 2) {
if (BF(root->left) == 1)R(root);
else if (BF(root->left) == -1) {
L(root->left);
R(root);
}
}
} else {
insert(root->right, v);
updateheight(root);
if (BF(root) == -2) {
if (BF(root->right) == -1)L(root);
else if (BF(root->right) == 1) {
R(root->right);
L(root);
}
}
}
}
int main() {
int n, data;
scanf("%d", &n);
node *root = NULL;
for (int i = 0; i < n; i++) {
scanf("%d", &data);
insert(root, data);
}
return 0;
}
4.动态规划
4.1 01背包问题(物品唯一)
n为物品总数,m
为背包容量,w[]
为重量,c[]
为价格,dp[j]
记录重为j
时背包的最高价格。
for (int i = 1; i < n; i++) {
for (int j = m; j >= w[i]; j--)
dp[j] = max(dp[j], dp[j - w[i]] + c[i]);
}
4.2完全背包问题(物品可以重复选)
与01背包问题中的枚举相逆
for (int i = 1; i < n; i++) {
for (int j = w[i]; j <= m; j++)
dp[j] = max(dp[j], dp[j - w[i]] + c[i]);
}
4.3最大连续子序列和
dp[i]
为以i
结尾时的最大连续和,ans
保存最大的连续子序列和。
dp[0] = 0;ans = -1;
for (int i = 1; i <= n; i++) {
dp[i] = max(A[i], A[i] + dp[i - 1]);
ans = max(ans, dp[i]);
}
4.4最长不下降子序列
dp[i]
为以i
结尾时的最大不下降子序列元素个数,ans
保存最大数量。
ans = -1;
for (int i = 1; i <= n; i++) {
dp[i] = 1;
for (int j = 1; j < i; j++) {
if (A[i] >= A[j] && dp[j] + 1 > dp[i])
dp[i] = dp[j] + 1;
}
ans = max(ans, dp[i]);
}
4.5最长公共子序列
dp[i][j]表示字符串A的前i位和字符串B的前j为的最长公共元素个数。
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 1000;
int dp[maxn][maxn] = {0};
char A[maxn], B[maxn];
int main() {
gets(A + 1);
gets(B + 1);
int lenA = strlen(A + 1);
int lenB = strlen(B + 1);
for (int i = 1; i <= lenA; i++) {
for (int j = 1; j <= lenB; j++) {
if (A[i] == B[j])dp[i][j] = dp[i - 1][j - 1] + 1;
else dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
printf("%d", dp[lenA][lenB]);
return 0;
}
4.6最长回文子串(动态规划做法)
dp[i][j]表示字符串第i位到字符串第j位之间是否是回文子串,复杂度O(n2)。
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 1000;
int dp[maxn][maxn] = {0};
char S[maxn];
int main() {
gets(S);
int len = strlen(S), ans = 1;
for (int i = 0; i < len; i++) {
dp[i][i] = 1;
if (i < len - 1 && S[i] == S[i + 1]) {
dp[i][i + 1] = 1;
ans = 2;
}
}
for (int L = 3; L <= len; L++) {
for (int i = 0; i + L - 1 < len; i++) {
int j = i + L - 1;
if (S[i] == S[j] && dp[i + 1][j - 1] == 1) {
dp[i][j] = 1;
ans = L;
}
}
}
printf("%d", ans);
return 0;
}
5.链表
struct node {
int data;
node *next;
node(int val) : data(val), next(NULL) {}
};
5.1链表的创建
首先自定一个无参数(-1)的首节点。
node *creat(int A[],int size) {
node *head = new node(-1);
node *temp = head;
for (int i = 0; i < size; i++) {
temp->next = new node(A[i]);
temp = temp->next;
}
return head->next;
}
5.2链表的反转
node *reverse(node *head) {
node *fhead = NULL, *p;
while (head != NULL) {
p = new node(head->data);
p->next = fhead;
fhead = p;
head = head->next;
}
return fhead;
}
后续补充…
如有错误,欢迎指正