排序
1.交换排序
1.1.快速排序
#include <iostream>
using namespace std;
int Arr[9] = { 32,23,45,8,231,56,876,43,2542 };
void QuickSort(int s, int e)
{
if (s >= e)
return;
int low = s, high = e, flag = Arr[low];
while (low < high)// 定义结束条件防止无限循环
{
while (flag <= Arr[high] && high > low)//直到遇到小于flag的值,否则high指针向左移动
high--;
Arr[low] = Arr[high];
while (flag >= Arr[low] && high > low)//直到遇到大于flag的值,否则low指针向右移动
low++;
Arr[high] = Arr[low];
}
Arr[low] = flag;
QuickSort(s, low - 1);
QuickSort(low + 1, e);
}
int main()
{
int s, e;
cout << "input start and end:";
cin >> s >> e;
QuickSort(s, e);
for (int i = s; i <= e; i++)
cout << Arr[i] << " ";
}
1.2.冒泡排序
#include <iostream>
using namespace std;
int Arr[9] = { 32,23,45,8,231,56,876,43,2542 };
void BubbleSort(int s, int e)
{
for (int i = 0; i < e - s; i++)//进行总长度-1次遍历
{
for (int j = s; j < e - s - i; j++)//进行总长度-1-i次交换
{
if (Arr[j + 1] < Arr[j])
{
int temp = Arr[j + 1];
Arr[j + 1] = Arr[j];
Arr[j] = temp;
}
}
}
for (int i = s; i <= e; i++)
cout << Arr[i] << " ";
}
int main()
{
int s, e;
cout << "input start and end:";
cin >> s >> e;
BubbleSort(s, e);
}
1.3.选择排序
#include <iostream>
using namespace std;
int Arr[9] = { 32,23,45,8,231,56,876,43,2542 };
void SelectSort(int s, int e)
{
for (int i = s; i <= e; i++)//从起点开始遍历
{
int flag = i;
for (int j = i + 1; j <= e; j++)//从下一个开始遍历看看是否有值Arr[j]小于当前Arr[i]
{
if (Arr[j] < Arr[flag])//若有则更新flag
flag = j;
}
if (Arr[flag] != Arr[i])//若flag确实被更新了,则将i和j的值交换
{
int temp = Arr[i];
Arr[i] = Arr[flag];
Arr[flag] = temp;
}
}
for (int i = s; i <= e; i++)
cout << Arr[i] << " ";
}
int main()
{
int s, e;
cout << "input start and end:";
cin >> s >> e;
SelectSort(s, e);
}
2.选择排序
2.1.直接插入排序
#include <iostream>
using namespace std;
int Arr[9] = { 32,23,45,8,231,56,876,43,2542 };
void DiInsertSort(int s, int e)
{
int i, j;
for (i = s + 1; i <= e; i++)//从第二个开始遍历值
{
if (Arr[i - 1] > Arr[i])
{
int temp = Arr[i];
for (j = i; temp < Arr[j - 1]; j--)//从j-1开始比较,找到合适的位置将Arr[i]插入
Arr[j] = Arr[j - 1];
Arr[j] = temp;
}
}
for (int i = s; i <= e; i++)
cout << Arr[i] << " ";
}
int main()
{
int s, e;
cout << "input start and end:";
cin >> s >> e;
DiInsertSort(s, e);
}
2.2.二分插入排序
#include <iostream>
using namespace std;
int Arr[9] = { 32,23,45,8,231,56,876,43,2542 };
void BiInsertSort(int s, int e)
{
int i, j;
for (i = s + 1; i <= e; i++)//从第二个开始遍历值
{
if (Arr[i] < Arr[i - 1])//如果这个值小于前一个值,开始插入
{
int low = s, high = i - 1, mid, temp = Arr[i];
while (low <= high)//二分查找Arr[i]合适的位置
{
mid = low + (high - low) / 2;
if (Arr[mid] > temp)
high = mid - 1;
else if (Arr[mid] < temp)
low = mid + 1;
}
for (int j = i; j > high + 1; j--)//插入Arr[i]
Arr[j] = Arr[j - 1];
Arr[high + 1] = temp;
}
}
for (int i = s; i <= e; i++)
cout << Arr[i] << " ";
}
int main()
{
int s, e;
cout << "input start and end:";
cin >> s >> e;
BiInsertSort(s, e);
}
2.3.希尔排序
#include <iostream>
using namespace std;
int Arr[9] = { 32,23,45,8,231,56,876,43,2542 };
void ShellSort(int s, int e)
{
int i, j, k, delta[3] = { 5,3,1 };
for (i = 0; i < 3; i++)//不同差值都要循环一次
{
for (j = s + delta[i]; j <= e; j += delta[i])//接下来的步骤和直接插入排序一样,不再赘述
{
if (Arr[j - delta[i]] > Arr[j])
{
int temp = Arr[j];
for (k = j; temp < Arr[k - delta[i]]; k-=delta[i])
Arr[k] = Arr[k - delta[i]];
Arr[k] = temp;
}
}
}
for (int i = s; i <= e; i++)
cout << Arr[i] << " ";
}
int main()
{
int s, e;
cout << "input start and end:";
cin >> s >> e;
ShellSort(s, e);
}
3.归并排序
#include <iostream>
using namespace std;
int Arr[20] = { 57, 12, 35, 88, 42, 66, 19, 73, 25, 51, 94, 17, 60, 7, 49, 10, 31, 83, 28, 95 };
int Temp[20] = {0};//拷贝数组,存放临时的排序后的数组内容
void Merge(int Arr[], int s, int m, int e, int Temp[])
{
int p1 = s, p2 = m + 1, p = 0;
while (p1 <= m && p2 <= e)
{
if (Arr[p1] < Arr[p2])//按照大小依次将第一个或者第二个数组的值放入Arr[]中
Temp[p++] = Arr[p1++];
else if (Arr[p1] > Arr[p2])
Temp[p++] = Arr[p2++];
}
while (p1 <= m)//如果第一个子数组还有内容而第二个子数组没有内容,则把第一个子数组中的剩下的值依次放入Temp[]中
Temp[p++] = Arr[p1++];
while (p2 <= e)
Temp[p++] = Arr[p2++];
for (int i = s; i <= e; i++)//把排好序的两个子数组放回原来的数组的对应位置
{
Arr[i] = Temp[i - s];
}
}
void MergeSort(int Arr[], int s, int e, int Temp[])//用来细分从s到e的这段数组,用Merge()函数来排序然后合并细分后的小数组
{
int m = 0;
if (s < e)
{
m = s + (e - s) / 2;//分隔数组为两个子数组
MergeSort(Arr, s, m, Temp);//两个子数组再重复递归分为更小的子数组
MergeSort(Arr, m + 1, e, Temp);
Merge(Arr, s, m, e, Temp);//排序,合并各级子数组
}
}
int main()
{
int s, e;
cout << "input start and end point:";
cin >> s >> e;
MergeSort(Arr, s, e, Temp);
for (int i = s; i <= e; i++)
cout << Arr[i] << " ";
}
4.二叉排序树
#include <iostream>
using namespace std;
struct BiTree
{
int V;
BiTree* Lch, * Rch;
};
void Traverse(BiTree* bt)//中序遍历从小到大输出所有值
{
if (!bt)
return;
Traverse(bt->Lch);
cout << bt->V << endl;
Traverse(bt->Rch);
}
void Create(BiTree*& bt, int v)
{
if (!bt)//若bt为null,说明可以在此处添加新值
{
bt = new BiTree;
bt->Lch = bt->Rch = nullptr;
bt->V = v;
}
else//否则说明需要继续向下搜索
{
if (v > bt->V)//小于此节点的值则向左搜索
Create(bt->Rch, v);
else if (v < bt->V)//否则向右搜索
Create(bt->Lch, v);
else//不得有重复的值
{
cout << "input again:";
cin >> v;
Create(bt, v);
}
}
}
void TreeSort()
{
BiTree* bt = nullptr;
int v;
cout << "input value:";
cin >> v;
while (v != 0)
{
Create(bt, v);
cout << "input value:";
cin >> v;
}
Traverse(bt);
}
int main()
{
TreeSort();
}
5.基数排序
#include <iostream>
#include <vector>
#include <algorithm>
#include<string>
using namespace std;
vector<int> Arr = { 170, 45, 75, 90, 802, 24, 2, 66 };
int GetNum(int n, int digit)
{
return (n / int(pow(10, digit - 1))) % 10;//获得n的第digit为数字
}
void RadixSort()
{
int MaxNum = *max_element(Arr.begin(), Arr.end()), Digit = 1;
while (Digit <= to_string(MaxNum).size())//以最大数的最大数位为边界条件
{
vector<int>Count(10, 0);//计数Digit数位各值的数量
vector<int>Copy(Arr.size(), 0);//临时存储排好的数组
for (int i = 0; i < Arr.size(); i++)
Count[GetNum(Arr[i], Digit)]++;//将Digit数位的各值计数,比如,个位上为1的数有3个即Count[1]=3
for (int i = 1; i <= 9; i++)
Count[i] += Count[i - 1];//将Count[i]数组的值更新为小于i的值的个数,比如原来Count[1]=3,Count[2]=1,那么此时Count[2]为4
for (int i = Arr.size() - 1; i >= 0; i--)//为Arr数组中的各值分配在Copy数组中的位置
{
Copy[Count[GetNum(Arr[i], Digit)] - 1] = Arr[i];
Count[GetNum(Arr[i], Digit)]--;//Digit位为GetNum(Arr[i], Digit)的可容纳空间减一
}
for (int i = 0; i < Arr.size(); i++)//将目前排好序的值再次存进原数组
Arr[i] = Copy[i];
Digit++;//判断的数位加1
}
for (int arr : Arr)
cout << arr << " ";
}
int main()
{
RadixSort();
return 0;
}
补充知识:
std::max_element
是 C++ STL 中的一个标准算法,用于在容器(如向量、数组等)中查找最大元素,并返回指向该最大元素的迭代器。该函数位于 <algorithm>
头文件中,并且可以用于所有标准容器,包括 std::vector、std::array、std::list、std::set 等。
for (int arr : Arr)
是一个基于范围的for循环(range-based for loop),用于遍历名为 Arr
的容器(可能是一个数组、向量或其他支持迭代的数据结构)中的每个元素。这个循环将容器中的每个元素依次赋值给变量 arr
,然后执行循环体中的代码。
6.堆排序
#include <iostream>
using namespace std;
int Arr[9] = { 32,23,45,8,231,56,876,43,2542 };
void HeapAdjust(int s, int e)
{
int i, temp = Arr[s];
for (i = s * 2 + 1; i <= e; i = i * 2 + 1)//从Arr[i]的左孩子开始遍历
{
if (Arr[i + 1] > Arr[i] && i < e)//若Arr[i+1]即Arr[i]的右孩子大于左孩子,那么需要和Arr[i]交换的孩子变为右孩子,否则仍然为左孩子
i++;
if (Arr[i] > temp)//若这个孩子确实比Arr[i]的父亲还要大,那么将孩子的值赋给父亲
{
Arr[s] = Arr[i];
s = i;//赋值后还要将s更新为当前孩子的位置
}
else
break;//否则说明孩子无需替代父亲,退出循环
}
Arr[s] = temp;//最后将父亲的值赋给孩子
}
void HeapSort()
{
int len = sizeof(Arr) / sizeof(int);
for (int i = (len - 2) / 2; i >= 0; i--)//从最后一个非叶子节点开始遍历,将无序的数组转变为大根堆
HeapAdjust(i, len - 1);
for (int i = 0; i < len - 1; i++)//开始循环调整大根堆,即将第一个元素与最后一个元素交换位置
{
int temp = Arr[len - i - 1];
Arr[len - 1 - i] = Arr[0];
Arr[0] = temp;//交换完毕
HeapAdjust(0, len - 2 - i);//由于大根堆被打乱,重新整理一下
}
for (int i = 0; i < len; i++)
cout << Arr[i] << " ";
}
int main()
{
HeapSort();
}
图
1.使用邻接矩阵创建图并且深度优先搜索遍历
#include <iostream>
using namespace std;
struct Graph
{
int D[20];
int M[20][20];
int Vnum, Enum;
};
bool CheckRepeat(int Arr[], int e, int temp)//检查是否有重复的值
{
for (int i = 0; i < e; i++)
{
if (Arr[i] == temp)
return 1;
}
return 0;
}
Graph CreateG()//生成无向图
{
Graph g;
memset(g.M, 0, sizeof(g.M));
cout << "input Vnum and Enum:";
cin >> g.Vnum >> g.Enum;
int temp;
for (int i = 0; i < g.Vnum; i++)
{
cout << "input data:";
cin >> temp;
while (cin.fail() || CheckRepeat(g.D, i, temp))//检查是否有输入错误或者重复输入
{
cout << "invalid input, input again:";
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cin >> temp;
}
g.D[i] = temp;
}
int s, e, w;
for (int i = 0; i < g.Enum; i++)
{
cout << "input start and end(index):";
cin >> s >> e;
cout << "input weight:";
cin >> w;
g.M[s][e] = g.M[e][s] = w;
}
return g;
}
void DFS(Graph g, int s, int* visit)
{
if (visit[s])//若此点已经被遍历过,直接返回
return;
visit[s] = 1;//若没有被遍历过,标记为1并输出
cout << g.D[s] << " ";
for (int i = 0; i < g.Vnum; i++)//检查与此点相邻的点继续遍历
{
if (g.M[s][i] && !visit[i])
DFS(g, i, visit);
}
}
void Start(Graph g)
{
int s, visit[20];
cout << "input start point:";
cin >> s;//输入起点下标
memset(visit, 0, sizeof(visit));//将状态矩阵置0
DFS(g, s, visit);
for (int i = 0; i < g.Vnum; i++)//防止图不连通,那么需要看看还有没有其他连通分支
DFS(g, i, visit);
}
int main()
{
Graph g = CreateG();
Start(g);
}
2.使用邻接矩阵创建图并且广度优先搜索遍历
#include <iostream>
#include<queue>
using namespace std;
struct Graph
{
int D[20];
int M[20][20];
int Vnum, Enum;
};
bool CheckRepeat(int Arr[], int e, int temp)//检查是否有重复的值
{
for (int i = 0; i < e; i++)
{
if (Arr[i] == temp)
return 1;
}
return 0;
}
Graph CreateG()//生成无向图
{
Graph g;
memset(g.M, 0, sizeof(g.M));
cout << "input Vnum and Enum:";
cin >> g.Vnum >> g.Enum;
int temp;
for (int i = 0; i < g.Vnum; i++)
{
cout << "input data:";
cin >> temp;
while (cin.fail() || CheckRepeat(g.D, i, temp))//检查是否有输入错误或者重复输入
{
cout << "invalid input, input again:";
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cin >> temp;
}
g.D[i] = temp;
}
int s, e, w;
for (int i = 0; i < g.Enum; i++)
{
cout << "input start and end(index):";
cin >> s >> e;
cout << "input weight:";
cin >> w;
g.M[s][e] = g.M[e][s] = w;
}
return g;
}
void BFS(Graph g, int s, int* visit)
{
if (visit[s])
return;
visit[s] = 1;
queue<int>q;
q.push(s);
while (!q.empty())
{
s = q.front();//保持队头更新
cout << g.D[s] << endl;//输出值
q.pop();//弹出队头
for (int i = 0; i < g.Vnum; i++)
{
if (!visit[i] && g.M[s][i])
{
q.push(i);
visit[i] = 1;
}
}
}
}
void Start(Graph g)
{
int s, visit[20];
cout << "input start point:";
cin >> s;//输入起点下标
memset(visit, 0, sizeof(visit));//将状态矩阵置0
BFS(g, s, visit);
for (int i = 0; i < g.Vnum; i++)//防止图不连通,那么需要看看还有没有其他连通分支
BFS(g, i, visit);
}
int main()
{
Graph g = CreateG();
Start(g);
}
3.使用邻接表创建图
#include <iostream>
#include<vector>
using namespace std;
struct Graph
{
int Weight;//邻接边的权重
int Des;//邻接点的序号
int DesNum = 0;//该点的邻接点个数
};
vector<vector<Graph>>graph(100);
void CreateGraph()
{
cout << "input how many vertex:";
int n;
cin >> n;
int m;
Graph g;
for (int i = 0; i < n; i++)
{
cout << "vertex " << i << ": input how many destination:";//输入每个点有几个邻接点
cin >> g.DesNum;
if (!g.DesNum)//若无邻接点,特殊处理
{
g.Des = g.Weight = -1;
graph[i].push_back(g);
}
for (int j = 0; j < g.DesNum; j++)
{
cout << "input destination and weight:";
cin >> g.Des >> g.Weight;
graph[i].push_back(g);
}
}
for (int i = 0; i < n; i++)
{
if (graph[i][0].DesNum)
{
cout << "vertex " << i << " have " << graph[i][0].DesNum << " destinations" << endl;
for (int j = 0; j < graph[i][0].DesNum; j++)
cout << "destination:" << graph[i][j].Des << " weight:" << graph[i][j].Weight << endl;
}
}
}
int main()
{
CreateGraph();
}
这种邻接表创建图使用vector容器取代了链表的形式,写起来和使用时更加方便。
4.Dijstra算法
#include <iostream>
using namespace std;
#define MAX 999;
struct Graph
{
int D[20];
int M[20][20];
int Vnum, Enum;
};
bool CheckRepeat(int Arr[], int e, int temp)//检查是否有重复的值
{
for (int i = 0; i < e; i++)
{
if (Arr[i] == temp)
return 1;
}
return 0;
}
Graph CreateG()//生成无向图
{
Graph g;
memset(g.M, 0, sizeof(g.M));
cout << "input Vnum and Enum:";
cin >> g.Vnum >> g.Enum;
int temp;
for (int i = 0; i < g.Vnum; i++)
{
cout << "input data:";
cin >> temp;
while (cin.fail() || CheckRepeat(g.D, i, temp))//检查是否有输入错误或者重复输入
{
cout << "invalid input, input again:";
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cin >> temp;
}
g.D[i] = temp;
}
int s, e, w;
for (int i = 0; i < g.Enum; i++)
{
cout << "input start and end(index):";
cin >> s >> e;
cout << "input weight:";
cin >> w;
g.M[s][e] = g.M[e][s] = w;
}
return g;
}
void Dijstra(Graph g) // 定义Dijstra函数,用于计算图中从指定起点到其他各顶点的最短路径
{
int* flag = new int[g.Vnum]; //创建一个数组flag,用于标记每个顶点是否已经被处理过
int* dist = new int[g.Vnum]; //创建一个数组dist,用于存储从起点到每个顶点的最短距离
int sign, s, mindist = MAX; //定义sign用于记录当前未处理顶点中距离最短的顶点,s为起点,mindist为当前最短距离
cout << "input start:"; //提示用户输入起点
cin >> s; //从用户输入中读取起点s
for (int i = 0; i < g.Vnum; i++) //初始化dist数组,将所有顶点的距离都设置为MAX
dist[i] = MAX;
memset(flag, 0, sizeof(flag)); //使用memset函数将flag数组中的所有元素都设置为0
dist[s] = 0; // 设置起点s到自身的距离为0
for (int i = 0; i < g.Vnum; i++) //主循环,对每个顶点进行处理
{
for (int j = 0; j < g.Vnum; j++) //找出当前未处理顶点中距离最短的顶点
{
if (!flag[j] && dist[j] < mindist) //如果顶点j未被处理且其距离小于当前最短距离
{
mindist = dist[j]; //更新最短距离为dist[j]
sign = j; //记录最短距离顶点为j
}
}
flag[sign] = 1; //将找到的最短距离顶点标记为已处理
for (int k = 0; k < g.Vnum; k++) //更新从起点到其他顶点的最短距离
{
if (!flag[k] && dist[sign] + g.M[sign][k] < dist[k] && g.M[sign][k]) //如果顶点k未被处理且通过顶点sign到达k的距离更短
dist[k] = dist[sign] + g.M[sign][k]; //更新dist[k]为更短的距离
}
}
for (int i = 0; i < g.VNum; i++)
cout << s << "->" << i << ":" << dist[i] << endl;
}
int main()
{
Graph g = CreateG();
Dijstra(g);
}
5.Floyd算法
#include <iostream>
using namespace std;
struct Graph
{
int D[20];
int M[20][20];
int Vnum, Enum;
};
bool CheckRepeat(int Arr[], int e, int temp)//检查是否有重复的值
{
for (int i = 0; i < e; i++)
{
if (Arr[i] == temp)
return 1;
}
return 0;
}
Graph CreateG()//生成无向图
{
Graph g;
memset(g.M, 0, sizeof(g.M));
cout << "input Vnum and Enum:";
cin >> g.Vnum >> g.Enum;
int temp;
for (int i = 0; i < g.Vnum; i++)
{
cout << "input data:";
cin >> temp;
while (cin.fail() || CheckRepeat(g.D, i, temp))//检查是否有输入错误或者重复输入
{
cout << "invalid input, input again:";
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cin >> temp;
}
g.D[i] = temp;
}
int s, e, w;
for (int i = 0; i < g.Enum; i++)
{
cout << "input start and end(index):";
cin >> s >> e;
cout << "input weight:";
cin >> w;
g.M[s][e] = g.M[e][s] = w;
}
return g;
}
void Floyd(Graph g) // 定义Floyd函数,用于计算图中从指定起点到其他各顶点的最短路径
{
for (int i = 0; i < g.Vnum; i++)
for (int j = 0; j < g.Vnum; j++)
for (int k = 0; k < g.Vnum; k++)
if (g.M[i][j] + g.M[j][k] < g.M[i][k])
g.M[i][k] = g.M[i][j] + g.M[j][k];//动态规划不断更新各店之间的最小距离
for (int i = 0; i < g.Vnum; i++)
for (int j = 0; j < g.Vnum; j++)
cout << i << " -> " << j << ":" << g.M[i][j] << endl;
}
int main()
{
Graph g = CreateG();
Floyd(g);
}
树
1.二叉树
1.1二叉树的各种基础操作
#include<iostream>
using namespace std;
#define MAXSIZE 100
typedef struct BT
{
char Data;
BT* Lc;
BT* Rc;
};
void PreCreate(BT*& t)
{
cout << "input data:";
char data;
cin >> data;
if (data == '-')
{
t = nullptr;
}
else
{
t = new BT;
t->Data = data;
t->Lc=t->Rc=nullptr;
PreCreate(t->Lc);
PreCreate(t->Rc);
}
}
void PreTraverse(BT*& bt)//先序遍历
{
if (bt == nullptr)
return;
cout << bt->Data << endl;
PreTraverse(bt->Lc);
PreTraverse(bt->Rc);
}
void InTraverse(BT*& bt)//中序遍历
{
if (bt == nullptr)
return;
InTraverse(bt->Lc);
cout << bt->Data << endl;
InTraverse(bt->Rc);
}
void PostTraverse(BT*& bt)//后序遍历
{
if (bt == nullptr)
return;
PostTraverse(bt->Lc);
PostTraverse(bt->Rc);
cout << bt->Data << endl;
}
void CopyTree(BT*& newbt, BT*& bt)//复制树
{
if (!bt)
{
newbt = nullptr;
return;
}
else
{
newbt = new BT;
newbt->Data = bt->Data;
CopyTree(newbt->Lc, bt->Lc);
CopyTree(newbt->Rc, bt->Rc);
}
}
int GetDepth(BT* bt)//树的深度
{
if (!bt)
return 0;
else
return GetDepth(bt->Lc) > GetDepth(bt->Rc) ? GetDepth(bt->Lc) + 1 : GetDepth(bt->Rc) + 1;
}
int GetNode(BT* bt)//节点数
{
if (!bt)
return 0;
else
return GetNode(bt->Lc) + GetNode(bt->Rc) + 1;
}
void DestroyBT(BT*& bt)//销毁树
{
if (!bt)
return;
DestroyBT(bt->Lc);
DestroyBT(bt->Rc);
delete bt;
}
int main()
{
BT *bt;
PreCreate(bt);
cout << "this is PreTraverse" << endl;
PreTraverse(bt);
cout << "this is InTraverse" << endl;
InTraverse(bt);
cout << "this is PostTraverse" << endl;
PostTraverse(bt);
BT* newbt = new BT;
CopyTree(newbt, bt);
cout << "this is PreTraverse of CopyTree" << endl;
PreTraverse(newbt);
cout << "Depth of BT is:" << GetDepth(bt) << endl;
cout << "Nodes of BT is:" << GetNode(bt) << endl;
DestroyBT(bt);
}
2.二叉排序树节点的删除
#include<iostream>
using namespace std;
#define MAXSIZE 10
#define ElemType int
typedef struct BSTree
{
ElemType data;
BSTree* LTree, *RTree;
}*BST;
void InTraverse(BST& bstree)
{
if (!bstree)
{
return;
}
InTraverse(bstree->LTree);
cout << bstree->data << " ";
InTraverse(bstree->RTree);
}
void Insert(BST& bstree, ElemType elem)
{
if (!bstree)
{
bstree = new BSTree;
bstree->data = elem;
bstree->LTree = bstree->RTree = nullptr;
}
else if (elem < bstree->data)
{
Insert(bstree->LTree, elem);
}
else if (elem > bstree->data)
{
Insert(bstree->RTree, elem);
}
}
void Create(BST &bstree)
{
bstree = nullptr;
ElemType data;
do
{
cout << "input data:" << endl;
cin >> data;
Insert(bstree, data);
} while (data);
//InTraverse(bstree);
}
BST FindMin(BST bstree) //查找最小节点,用于删除有两个子节点的情况
{
if (!bstree)
{
return nullptr;
}
else if (bstree->LTree == nullptr)
{
return bstree;
}
else
{
return FindMin(bstree->LTree);
}
}
void Delete(BST& bstree, ElemType elem) //删除节点函数
{
if (bstree == nullptr) //空树直接返回
{
return;
}
else if (elem < bstree->data) //待删除元素在左子树中
{
Delete(bstree->LTree, elem);
}
else if (elem > bstree->data) //待删除元素在右子树中
{
Delete(bstree->RTree, elem);
}
else //找到待删除元素
{
if (bstree->LTree == nullptr && bstree->RTree == nullptr) //叶子节点,直接删除
{
delete bstree;
bstree = nullptr;
}
else if (bstree->LTree == nullptr) //只有一个子节点,用子节点替代被删除节点位置
{
BST temp = bstree;
bstree = bstree->RTree;
delete temp;
}
else if (bstree->RTree == nullptr) //只有一个子节点,用子节点替代被删除节点位置
{
BST temp = bstree;
bstree = bstree->LTree;
delete temp;
}
else //有两个子节点,找到中序后继替代被删除节点位置,然后删除中序后继
{
BST temp = FindMin(bstree->RTree); //找到右子树中最小的节点,即中序后继
bstree->data = temp->data; //替代被删除节点的数据域值
Delete(bstree->RTree, temp->data); //删除中序后继节点
}
}
}
int main()
{
BST bstree = new BSTree;
Create(bstree);
InTraverse(bstree);
cout<<endl;
Delete(bstree,16);
InTraverse(bstree);
}
3.哈夫曼树
#include<iostream>
using namespace std;
typedef struct HT
{
int W;
int P, Lc, Rc;
};
void Print(HT* ht, int num)
{
for (int i = 1; i <= num; i++)
{
cout << i << ":"<< ht[i].W << " Parent:" << ht[i].P << " Lc:" << ht[i].Lc << " Rc:" << ht[i].Rc << endl;
}
}
void Select(HT* ht, int Length, int& min1, int& min2)
{
min1 = min2 = 0;
int i;
for (i = 1; i <= Length; ++i)
{
if (ht[i].P == 0)
{
{
if (min1 == 0 || ht[i].W < ht[min1].W)
{
min2 = min1;
min1 = i;
}
else if (min2 == 0 || ht[i].W < ht[min2].W)
{
min2 = i;
}
}
}
}
cout << "min1:" << ht[min1].W << " min2:" << ht[min2].W << endl;
}
void Create(HT*& ht)
{
cout << "input nodes num:";
int num, min1, min2;
cin >> num;
ht = new HT[2 * num];//注意是2*num,不是2*num-1,因为下标为0的地方无值
for (int i = 1; i <= num; i++)
{
cout << "input data:";
cin >> ht[i].W;
}
for (int i = 0; i < 2 * num; i++)
{
ht[i].P = ht[i].Lc = ht[i].Rc = 0;
}
for (int i = num + 1; i < 2 * num; i++)
{
Select(ht, i-1, min1, min2);
ht[i].W = ht[min1].W + ht[min2].W;
ht[i].Lc = min1;
ht[i].Rc = min2;
ht[min1].P = ht[min2].P = i;
}
Print(ht, 2 * num - 1);
}
int main()
{
HT* ht;
Create(ht);
}
4.层次遍历(队列)
#include <iostream>
#include<queue>
using namespace std;
struct BiTree
{
int D;
BiTree* L, * R;
};
void Create(BiTree*& bt)//创建一个二叉树
{
int data;
cout << "input data:";
cin >> data;
if (data != 0)
{
bt = new BiTree;
bt->D = data;
bt->L = bt->R = nullptr;
Create(bt->L);
Create(bt->R);
}
}
void LayerPrint(BiTree* bt)//层次遍历
{
queue<BiTree>q;
q.push(*bt);
while (!q.empty())
{
if(q.front().L)//左孩子存在,入队
q.push(*q.front().L);
if(q.front().R)//右孩子存在,入队
q.push(*q.front().R);
cout << q.front().D << endl;//孩子处理完成,输出当前值
q.pop();//弹出当前值,下一个元素作为队首
}
}
int main()
{
BiTree* bt = nullptr;
Create(bt);
LayerPrint(bt);
}
5.深度优先搜索遍历(栈)
#include <iostream>
#include<stack>
using namespace std;
struct BiTree
{
int D;
BiTree* L, * R;
};
void Create(BiTree*& bt)//创建一个二叉树
{
int data;
cout << "input data:";
cin >> data;
if (data != 0)
{
bt = new BiTree;
bt->D = data;
bt->L = bt->R = nullptr;
Create(bt->L);
Create(bt->R);
}
}
void DFSPrint(BiTree* bt)//深度优先搜索(通过栈)
{
stack<BiTree>s;
BiTree* temp = bt;
while (!s.empty() || temp)
{
if (temp)//判断temp是否存在,若存在则入栈并且尝试把他的左孩子入栈
{
s.push(*temp);
temp = temp->L;
}
else//temp不存在,将此节点值输出,尝试将其右孩子入栈然后将此节点弹栈
{
cout << s.top().D << endl;
temp = s.top().R;
s.pop();
}
}
}
int main()
{
BiTree* bt = nullptr;
Create(bt);
DFSPrint(bt);
}
6.AVL
#include <iostream>
#include <algorithm>
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
int height;
TreeNode(int v) : val(v), left(NULL), right(NULL), height(1) {}
};
// 获取节点的高度
int height(TreeNode* node) {
return node == NULL ? 0 : node->height;
}
// 计算节点的平衡因子:左子树高度 - 右子树高度
int getBalance(TreeNode* node) {
return node == NULL ? 0 : height(node->left) - height(node->right);
}
// 右旋操作:处理左左(LL)情况
TreeNode* rightRotate(TreeNode* y) {
TreeNode* x = y->left;
TreeNode* T2 = x->right;
// 执行右旋:x上升为根,y下沉到x的右子树,T2成为y的左子树
x->right = y;
y->left = T2;
// 更新y和x的高度
y->height = std::max(height(y->left), height(y->right)) + 1;
x->height = std::max(height(x->left), height(x->right)) + 1;
// 返回新的根节点
return x;
}
// 左旋操作:处理右右(RR)情况
TreeNode* leftRotate(TreeNode* x) {
TreeNode* y = x->right;
TreeNode* T2 = y->left;
// 执行左旋:y上升为根,x下沉到y的左子树,T2成为x的右子树
y->left = x;
x->right = T2;
// 更新x和y的高度
x->height = std::max(height(x->left), height(x->right)) + 1;
y->height = std::max(height(y->left), height(y->right)) + 1;
// 返回新的根节点
return y;
}
// 插入新节点,并在必要时进行平衡调整
TreeNode* insert(TreeNode* node, int key) {
// 常规的二叉搜索树插入操作
if (node == NULL)
return new TreeNode(key);
if (key < node->val)
node->left = insert(node->left, key);
else if (key > node->val)
node->right = insert(node->right, key);
else
return node; // 不允许重复的键
// 更新当前节点的高度
node->height = 1 + std::max(height(node->left), height(node->right));
// 获取当前节点的平衡因子
int balance = getBalance(node);
// 左左(LL)情况:左子树过重且新节点在左子树的左侧 -> 右旋
if (balance > 1 && key < node->left->val)
return rightRotate(node);
// 右右(RR)情况:右子树过重且新节点在右子树的右侧 -> 左旋
if (balance < -1 && key > node->right->val)
return leftRotate(node);
// 左右(LR)情况:左子树过重且新节点在左子树的右侧 -> 先左旋后右旋
if (balance > 1 && key > node->left->val) {
node->left = leftRotate(node->left);
return rightRotate(node);
}
// 右左(RL)情况:右子树过重且新节点在右子树的左侧 -> 先右旋后左旋
if (balance < -1 && key < node->right->val) {
node->right = rightRotate(node->right);
return leftRotate(node);
}
// 如果树是平衡的,直接返回当前节点
return node;
}
// 中序遍历AVL树,按从小到大的顺序输出节点的值
void inOrder(TreeNode* root) {
if (root != NULL) {
inOrder(root->left);
std::cout << root->val << " ";
inOrder(root->right);
}
}
int main() {
TreeNode* root = NULL;
// 插入一些节点到AVL树中
root = insert(root, 10);
root = insert(root, 20);
root = insert(root, 30);
root = insert(root, 40);
root = insert(root, 50);
root = insert(root, 25);
// 输出中序遍历结果,验证AVL树结构
std::cout << "In-order traversal of the constructed AVL tree is: \n";
inOrder(root);
return 0;
}
原理解释以及AVL的丝滑变换:平衡二叉树(AVL树)_哔哩哔哩_bilibili
2.并查集
KMP算法
#include<iostream>
using namespace std;
#include<string>
void Next(string& substr, int* next)
{
int MaxLen = 0, i = 1;//注意此处i要初始化为1,以便和str[0]比较
next[0] = 0;
while (i < substr.length())//内容分为两部分
{
if (substr[i] == substr[MaxLen])//第一部分:substr的最大公共前后缀可以加一
next[i++] = ++MaxLen;
else//第二部分:substr的最大公共前后缀无法加一
{
if (MaxLen == 0)//如果此时最大公共前后缀还是0,显然next数组下一个也是0
next[i++] = 0;
else//如果不是0,那么最大公共前后缀返回到之前的一个值
MaxLen = next[MaxLen - 1];
}
}
i = 0;
while (i < substr.length())
{
cout << next[i++] << " ";
}
}
void KMP()
{
string str, substr;
cout << "input str:";
cin >> str;
cout << "input substr:";
cin >> substr;
int* next = new int[100];
Next(substr, next);
int i = 0, j = 0;
while (i < str.length())//内容分为两种情况
{
if (str[i] == substr[j])//第一种情况:str和substr的对应值匹配,i++,j++
{
i++;
j++;
}
else if (j > 0)//第二种情况(匹配中断)之一:substr已经匹配到一些值了,但是中断了
j = next[j - 1];
else//第二种情况(匹配中断)之二:substr还没有匹配到任何值就中断了,只能i++,主串向后一位
i++;
if (substr.length() - 1 == j)
{
cout << "from " << i - j << " to" << i << endl;
return;
}
}
cout << endl;
cout << j << " " << substr.length() << endl;
cout << "\nmatch failed" << endl;
}
int main()
{
KMP();
}
队列&栈&顺序表
1.线性队列
#include<iostream>
using namespace std;
#define MAXSIZE 100
#define ElemType int
typedef struct SQ
{
ElemType* base;
int front, rear;
};
void Init(SQ* sq)
{
sq->base = new ElemType[100];
if (!sq->base)
{
cout << "memory allocate failed" << endl;
return;
}
sq->front = sq->rear = 0;
}
bool IsEmpty(SQ* sq)
{
return sq->front == sq->rear;
}
bool IsFull(SQ* sq)
{
return (sq->rear + 1) % MAXSIZE == sq->front;
}
void Push(SQ* sq)
{
if (IsFull(sq))
{
cout << "SQ is full" << endl;
return;
}
cout << "input data:";
int data;
cin >> data;
sq->base[sq->rear] = data;
sq->rear = (sq->rear + 1) % MAXSIZE;
}
void Pop(SQ* sq)
{
if (IsEmpty(sq))
{
cout << "SQ is empty" << endl;
return;
}
int data = sq->base[sq->front];
sq->front = (sq->front + 1) % MAXSIZE;
cout << "pop " << data << " out" << endl;
}
void GetFront(SQ* sq)
{
cout << "fornt data of SQ is:" << sq->base[sq->front] << endl;
}
void GetLength(SQ* sq)
{
cout << "Length of SQ is:" << (sq->rear - sq->front + MAXSIZE) % MAXSIZE << endl;
}
int main()
{
SQ sq;
Init(&sq);
for (int i = 0; i < 5; i++)
{
Push(&sq);
}
GetLength(&sq);
Pop(&sq);
GetFront(&sq);
}
2.链式队列
#include<iostream>
using namespace std;
#define ElemType int
typedef struct QN
{
ElemType Data;
QN* Next;
};
typedef struct LQ
{
QN* rear;
QN* front;
};
void Init(LQ* lq)
{
if (!(lq->front = lq->rear = new QN))
{
cout << "memory allocate failed" << endl;
return;
}
lq->front->Next = nullptr;
}
bool IsEmpty(LQ* lq)
{
return !(lq->front);
}
void Push(LQ* lq)
{
QN* temp = new QN;
if (!temp)
{
cout << "failed" << endl;
return;
}
cout << "input data:";
ElemType data;
cin >> data;
temp->Data = data;
temp->Next = nullptr;
lq->rear->Next = temp;
lq->rear = temp;
}
void Pop(LQ* lq)
{
if (IsEmpty(lq))
{
cout << "LQ is empty" << endl;
return;
}
QN* temp = lq->front->Next;
lq->front = lq->front->Next->Next;
int data = temp->Data;
cout << "pop " << data << " out" << endl;
delete temp;
}
void GetFront(LQ* lq)
{
cout << "front data of LQ is:" << lq->front->Data << endl;
}
int main()
{
LQ lq;
Init(&lq);
for (int i = 0; i < 5; i++)
{
Push(&lq);
}
Pop(&lq);
GetFront(&lq);
}
3.线性栈
#include<iostream>
using namespace std;
#define ElemType int
#define MAXSIZE 100
typedef struct SqS
{
ElemType* base;
ElemType* top;
int Size;
};
void Init(SqS* sqs)
{
sqs->base = new ElemType[MAXSIZE];
if (!sqs->base)
{
cout << "memory allocate failed" << endl;
return;
}
sqs->top = sqs->base;
sqs->Size = MAXSIZE;
}
void Push(SqS* sqs)
{
if (sqs->top-sqs->base==MAXSIZE)
{
cout << "Sqstack is full" << endl;
return;
}
int data;
cout << "input data:";
cin >> data;
*(sqs->top++) = data;
}
void Pop(SqS* sqs)
{
if (sqs->top==sqs->base)
{
cout << "Sqstack is empty" << endl;
return;
}
int data = *(--sqs->top);
cout << "pop " << data << " out" << endl;
}
bool IsEmpty(SqS* sqs)
{
return sqs->base == sqs->top;
}
bool IsFull(SqS* sqs)
{
return sqs->top - sqs->base == MAXSIZE;
}
void GetTop(SqS* sqs)
{
cout << "the top data is:" << *(--sqs->top) << endl;
}
int main()
{
SqS sqs;
Init(&sqs);
for (int i = 0; i < 5; i++)
{
Push(&sqs);
}
Pop(&sqs);
GetTop(&sqs);
}
4.链式栈
#include<iostream>
using namespace std;
#define ElemType int
typedef struct LS
{
ElemType Data;
LS* Next;
};
void Init(LS*& ls)
{
ls = new LS;
if (!ls)
{
cout << "initailize failed" << endl;
return;
}
ls->Next = nullptr;
}
void Push(LS*& ls)
{
int data;
cout << "input data:";
cin >> data;
LS* newnode = new LS;
LS* copyls = ls;
newnode->Data = data;
newnode->Next = nullptr;
copyls->Next = newnode;
copyls = newnode;
}
void Pop(LS*& ls)
{
if (!ls->Next)
{
cout << "LS is empty" << endl;
return;
}
int data = 0;
LS* temp = ls->Next;
LS* pretemp = ls;
while (temp)
{
data = temp->Data;
if (!temp->Next)
{
cout << "pop " << data << " out" << endl;
delete temp;
pretemp->Next = nullptr;
return;
}
pretemp = pretemp->Next;
temp = temp->Next;
}
}
int main()
{
LS* ls;
Init(ls);
LS* temp = ls;
for (int i = 0; i < 3; i++)
{
Push(temp);
temp = temp->Next;
}
Pop(ls);
Pop(ls);
Pop(ls);
}
5.线性表
#include<iostream>
using namespace std;
#define MAXSIZE 100
#define ElemType int
typedef struct
{
ElemType *Data;
int Length;
}SqL;
void Init(SqL *sql)
{
sql->Data = new ElemType[MAXSIZE];
if (!sql->Data)
{
cout << "memory allcate failed" << endl;
delete[]sql->Data;
return;
}
sql->Length = 0;
cout << "create SqL successfully" << endl;
}
void Insert(SqL* sql)
{
if (sql->Length>MAXSIZE)
{
cout << "out of range" << endl;
return;
}
int index = 0, data = 0;
cout << "input index and data:";
cin >> index >> data;
if (index > sql->Length)
{
sql->Data[sql->Length] = data;
}
else if (index == 1)
{
for (int i = sql->Length-1; i >= 0; i--)
{
sql->Data[i + 1] = sql->Data[i];
}
sql->Data[0] = data;
}
else
{
for (int i = sql->Length; i >= index - 1; i--)
{
sql->Data[i + 1] = sql->Data[i];
}
sql->Data[index-1] = data;
}
sql->Length++;
}
void Browse(SqL* sql)
{
for (int i = 0; i < sql->Length; i++)
{
cout << i + 1 << ":" << sql->Data[i] << endl;
}
}
void Delete(SqL* sql)
{
int choice = 0;
cout << "Choice:1.delete by index,2.delete by data,input choice:";
cin >> choice;
if (choice == 1)
{
int index;
cout << "input index:";
cin >> index;
if (index<1 || index>sql->Length)
{
cout << "out of range" << endl;
return;
}
for (int i = index-1; i < sql->Length-1; i++)
{
sql->Data[i] = sql->Data[i + 1];
}
sql->Length--;
Browse(sql);
}
else
{
int data;
cout << "input data:";
cin >> data;
for (int i = 0; i < sql->Length; i++)
{
if (sql->Data[i] == data)
{
for (int j = i; j <= sql->Length-1; j++)
{
sql->Data[j] = sql->Data[j+1];
}
sql->Length--;
}
}
for (int i = 0; i < sql->Length; i++)
{
cout << i + 1 << ":" << sql->Data[i] << endl;
}
}
}
void Locate(SqL* sql)
{
int Choice = 0;
cout << "1.locate by index,2.locate by data,input choice:";
cin >> Choice;
if (Choice == 1)
{
int index;
cout << "input index:";
cin >> index;
if (index < 1 || index>sql->Length)
{
cout << "out of range" << endl;
return;
}
cout << index << ":" << sql->Data[index - 1];
}
else
{
int data;
cout << "input data:";
cin >> data;
for (int i = 0; i < sql->Length; i++)
{
if (data == sql->Data[i])
{
cout << "index of " << data << " is " << i + 1 << endl;
}
}
}
}
bool IsEmpty(SqL* sql)
{
if (sql->Length == 0)
{
cout << "Empty" << endl;
return 1;
}
}
bool IsFull(SqL* sql)
{
if (sql->Length == MAXSIZE)
{
cout << "Full" << endl;
return 1;
}
}
int main()
{
SqL sql;
Init(&sql);
for (int i = 0; i < 4; i++)
{
Insert(&sql);
}
Browse(&sql);
Delete(&sql);
Locate(&sql);
IsEmpty(&sql);
IsFull(&sql);
}
6.链式表
#include<iostream>
using namespace std;
#define ElemType int
typedef struct LL
{
ElemType Data;
LL* Next;
};
void Init(LL*& head)
{
head = new LL;
head->Next = nullptr;
if (!head)
{
cout<<"memory allocate failed" << endl;
return;
}
}
void HeadInsert(LL*& head)
{
LL* tail = new LL;
if (!tail)
{
cout << "failed" << endl;
return;
}
ElemType data;
cout << "input data:";
cin >> data;
tail->Data = data;
tail->Next = head->Next;
head->Next = tail;
}
void TailInsert(LL*& head)
{
LL* tail=head;
LL* temp = new LL;
ElemType data;
cout << "input data:";
cin >> data;
temp->Data = data;
temp->Next = nullptr;
tail->Next = temp;
tail = temp;
}
void Browse(LL* head)
{
if (!head->Next)
cout << "Linked List is empty" << endl;
int i = 1;
LL* temp = head->Next;
while (temp)
{
cout << i << ":" << temp->Data << endl;
temp = temp->Next;
i++;
}
}
void Locate(LL* head)
{
LL* temp = head->Next;
ElemType data;
int i=1;
cout << "input data:";
cin >> data;
while (temp)
{
if (temp->Data == data)
{
cout << "the index of " << data << " is " << i << endl;
break;
}
i++;
}
}
void Delete(LL* head)
{
LL* temp = head;
while (temp)
{
temp = head;
head = head->Next;
delete temp;
}
}
void Clear(LL* head)
{
LL* temp1 = head->Next;
LL* temp2 = new LL;
while (temp1)
{
temp2 = temp1;
temp1 = temp1->Next;
delete temp2;
}
head->Next = nullptr;
if (head->Next)
cout << "clearing failed" << endl;
}
int main()
{
LL *head;
Init(head);
for (int i = 0; i < 5; i++)
{
HeadInsert(head);
}
Clear(head);
LL* copyhead = head;
for (int i = 0; i < 5; i++)
{
TailInsert(copyhead);
copyhead = copyhead->Next;
}
Browse(head);
Locate(head);
Delete(head);
}