数据结构与算法学习笔记(代码)(更新中)

排序

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);
}

2.并查集

【算法与数据结构】—— 并查集-CSDN博客

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);

}

  • 12
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值