一、线性表
排序:冒泡排序、选择排序、快速排序、归并排序
查找:二分查找
二、树
遍历:递归(前中后序、层次)
排序:大根堆、小根堆
哈夫曼树
三、图
广度优先遍历
深度优先遍历
最小生成树:Prim算法、Kus算法
最短路径:Dij算法
一、线性表
- 排序算法
冒泡排序:
//冒泡排序
void bubbleSort(int *arr, int length) {
//外层for循环控制查找第i大的元素
for (int i = length; i > 0; i--) {
//内层for循环,从0开始依次比较前后两个元素
for (int j = 0; j < i - 1; j++) {
//如果arr[j] > arr[j+1],则交换位置
if (arr[j] > arr[j + 1])
swap(arr[j], arr[j + 1]);
}
}
}
选择排序:
void selectionSort(int *arr,int length) {
int minIndex;
for (int i = 0; i < length; i++) {
minIndex = i; //记录第i小值的下标
//查找[i, length]范围内的最小值下标
for (int j = i + 1; j < length; j++) {
if (arr[minIndex] > arr[j])
minIndex = j;
}
swap(arr[minIndex], arr[i]); //把第i小的值,交换到i的位置
}
}
归并排序:
//将arr[l...mid]和arr[mid+1...r]两部分进行归并
void merge(int *arr, int l, int mid, int r) {
int *aux = new int[r - l + 1];
for (int i = l; i <= r; i++) {
aux[i - l] = arr[i];
}
// 初始化,i指向左半部分的起始索引位置l;j指向右半部分起始索引位置mid+1
int i = l, j = mid + 1;
for (int k = l; k <= r; k++) {
//有一组元素已经全部入队
if (i > mid) { // 如果左半部分元素已经全部处理完毕
arr[k] = aux[j - l]; j++;
continue;
} else if (j > r) { // 如果右半部分元素已经全部处理完毕
arr[k] = aux[i - l]; i++;
continue;
}
//两组元素等待入队
if (aux[i - l] < aux[j - l]) { // 左半部分所指元素 < 右半部分所指元素
arr[k] = aux[i - l]; i++;
} else { // 左半部分所指元素 >= 右半部分所指元素
arr[k] = aux[j - l]; j++;
}
}
delete[] aux; //释放创建的空间
}
// 递归使用归并排序,对arr[l...r]的范围进行排序
void mergeSort(int *arr, int l, int r) {
if (l >= r)
return;
int mid = (l + r) / 2;
mergeSort(arr, l, mid); //递归l到mid
mergeSort(arr, mid + 1, r); //递归mid+1到r
merge(arr, l, mid, r); //对l到r进行排序
}
快速排序:
// 对arr[low...high]部分进行partition操作
// 返回low, 使得arr[low]之前的都小于arr[low]; arr[low]之后的都大于arr[low]
int partition(int *arr, int low, int high) {
int pivotkey = arr[low];
while (low < high) {
while (low < high&&arr[high] >= pivotkey)
high--;
swap(arr[low], arr[high]);
while (low < high&&arr[low] <= pivotkey)
low++;
swap(arr[low], arr[high]);
}
return low;
}
// 对arr[l...r]部分进行快速排序
void quickSort(int *arr, int l, int r) {
if (l >= r)
return;
int p = partition(arr, l, r); //得到l处元素应该处于的位置 p
quickSort(arr, l, p - 1); //对前半部分(l到p-1)的元素进行快速排序
quickSort(arr, p + 1, r); //对后半部分(p+1到r)的元素进行排序
}
- 查找算法
二、树
- 遍历
//树的定义
typedef struct BiTree {
int data;
BiTree *leftChild;
BiTree *rightChild;
}*T;
先序遍历:
//先访问根节点,再访问左子树,最后访问右子树
//递归遍历
void preOrder(BiTree *T) {
if (T != NULL) {
visit(T);
preOrder(T -> leftChild);
preOrder(T -> rightChild);
}
}
//非递归遍历
void PreOrder(BiTree *root) {
//判断是否为空树,空树直接返回
if (root == NULL){
cout<<"Empty Tree!" << endl;
return ;
}
InitStack(S); //创建栈
//循环结束条件为当前节点为空且栈为空
while (root != NULL || !StackEmpty(S)) {
if (root != NULL) {
//当前节点不为空,访问当前节点
visit(root);
//右子节点不为空时入栈右子节点
if (root->rightChild != NULL)
Push(S, root->rightChild);
//指向左子节点
root = root->leftChild;
} else {
//当前节点为空时,访问栈顶元素
Pop(S, root);
}
}
}
中序遍历:
//先访问左子树,再访问根节点,最后访问右子树
//递归遍历
void inOrder(BiTree *T) {
if (T != NULL) {
inOrder(T -> leftChild);
visit(T);
inOrder(T -> rightChild);
}
}
//非递归遍历
void InOrder(BiTree *root) {
//判断是否为空树,空树直接返回
if (root == NULL){
cout<<"Empty Tree!" << endl;
return ;
}
InitStack(S); //创建栈
//循环结束条件为当前节点为空且栈为空
while (root != NULL || StackEmpty(S)) {
if (root != NULL) { //当前节点不为空,入栈;指向左子树
Push(S, root);
root = root->leftChild;
} else { //当前节点为空,访问栈顶元素;指向右子树
Pop(S, root);
visit(root);
root = root->rightChild;
}
}
}
后续遍历:
//先访问左子树,再访问右子树,最后访问根节点
void postOrder(BiTree *T) {
if (T != NULL) {
postOrder(T->leftChild);
postOrder(T->rightChild);
visit(T);
}
}
//非递归
//思想:后序遍历为左右跟,可以先根右左访问,再倒置
void PostOrder(BiTree* root) {
//判断是否为空树,空树直接返回
if (root == NULL){
cout<<"Empty Tree!" << endl;
return ;
}
InitStack(S);
InitStack(Data);
int data;
//循环结束条件为当前节点为空且栈为空
while (root != NULL || !StackEmpty(S)) {
if (root != NULL) {
//当前节点不为空,入栈当前节点值
Push(Data, root->data);
//右子节点不为空时入栈左子节点
if (root->leftChild != NULL)
Push(S, root->leftChild);
//指向右子节点
root = root->rightChild;
}
else {
//当前节点为空时,访问栈顶元素
Pop(S, root);
}
}
//倒序输出节点值(由“根右左”变为“左右根”)
while (StackEmpty(Data)) {
Pop(Data, data);
cout << data;
}
}
层次遍历
//二叉树层次遍历
void LevelOrder(BiTree *root) {
InitQueue(Q); //初始化指针
BiTree tmp; //创建临时变量用于访问节点
Q.push(root); //入队根节点
while (!Q.empty()) {
tmp = Q.pop(); //取出队头元素,并访问
visit(tmp);
if (tmp.leftChild != NULL) //判断左子树是否为空,不为空时加入队列
Q.push(tmp.leftChild);
if (tmp.rightChild != NULL) //判断右子树是否为空,不为空时加入队列
Q.push(tmp.rightChild);
}
}
- 堆排序
大根堆
void HeapAdjust(int *arr, int low, int high) {
int rc = arr[low]; //rc为本次调整的根的值
for (int j = 2 * low; j < high; j *= 2) {
if (j < high && arr[j] < arr[j + 1]) //j为rc左右子树中较大的(j<high保证了不会越界)
j++;
if (rc > arr[j]) //以rc为根的子树符合大根堆,直接退出调整
break;
//调整以rc为根的子树,使得根节点大于左右子树
arr[low] = arr[j];
low = j;
}
arr[low] = rc;
}
void HeapSort(int *arr,int length) {
for (int i = length / 2; i > 0; i--) //对数组进行堆排序
HeapAdjust(arr, i, length);
for (int i = length; i > 1; i--) { //依次输出数组
cout << arr[1];
arr[1] = arr[i];
HeapAdjust(arr, 1, i - 1);
}
}
小根堆
void HeapAdjust(int *arr, int low, int high) {
int rc = arr[low]; //rc为本次调整的根的值
for (int j = 2 * low; j < high; j *= 2) {
if (j < high && arr[j] > arr[j + 1]) //j为rc左右子树中较小的(j<high保证了不会越界)
j++;
if (rc < arr[j]) //以rc为根的子树符合大根堆,直接退出调整
break;
//调整以rc为根的子树,使得根节点大于左右子树
arr[low] = arr[j];
low = j;
}
arr[low] = rc;
}
void HeapSort(int *arr,int length) {
for (int i = length / 2; i > 0; i--) //对数组进行堆排序
HeapAdjust(arr, i, length);
for (int i = length; i > 1; i--) { //依次输出数组
cout << arr[1];
arr[1] = arr[i];
HeapAdjust(arr, 1, i - 1);
}
}
- 哈夫曼树
三、图
- 广度优先遍历
- 深度优先遍历(计算联通分量
- 最小生成树
- 最短路径