第二章

我觉得此章节的数据结构可以实现一下

数组实现栈

#include<iostream>using namespace std;struct  stack
{int top;//下一个应该放的元素位置int mCapacity;int *p;stack(int capacity){mCapacity = capacity;p = new int[mCapacity];top = 0;}int pop(){if (top==0){cout << "栈是空的" << endl;}else{top--;//默认下一个位置就是待插入元素就可以了,并没有实际删除return  p[top];}return -1;}int push(int x){int ret = -1;if (top>=mCapacity){cout << "已经满了" << endl;}else{p[top] = x;top++;ret = x;}return ret;}int gettop(){if (top==0){return -1;}else{return p[top-1];}}int getsize(){return top;}
};
int main()
{stack s(5);/*for (int i=0;i<5;i++){s.push(i);cout << "size()="<<  s.getsize() << endl;}for (int i = 0;i <10;i++){cout << "pop()=" << s.pop() << endl;}*///cout << "size()=" << s.getsize() << endl;for (int i =3;i < 5;i++){s.push(i);cout << "gettop()=" << s.gettop() << endl;//cout << "size()=" << s.getsize() << endl;}}

链表实现栈

#include<iostream>using namespace std;//只能实现头插法,才能用链表
struct Node
{int data;Node *next;Node(){data = 0;next = nullptr;}Node(int x){data =x;next = nullptr;}
};struct linStack
{Node * dummpy;linStack(){dummpy = new Node();}int pop(){if (dummpy->next==NULL)//只有一个空节点,{cout << "栈现在是空的" << endl;return -1;}else//注意一定要采用头插法{int ret = dummpy->next->data;dummpy->next = dummpy->next->next;return ret;}}int push(int x){Node * newnode = new Node(x);newnode->next = dummpy->next;dummpy->next = newnode;return -1;}int getTop(){if (dummpy->next!=nullptr){return dummpy->next->data;}else{return -1;}}int getsize(){Node * p = dummpy->next;int count = 0;while (p != nullptr){count++;p = p->next;}return count;}};int main()
{linStack s;for (int i=0;i<5;i++){s.push(i);//cout << "getsize=" << s.getsize() << endl;}for (int i = 0;i < 10;i++){cout << "pop()=" << s.pop() << endl;}for (int i = 3;i < 10;i++){s.push(i);cout << "s.top()=" << s.getTop() << endl;}}

队列:
数组实现循环队列

#include<iostream>
#include<algorithm>
using namespace std;struct quque
{int mCapacity;int *p;int head ;int tail;quque(int capacity){mCapacity = capacity;p = new int[mCapacity];tail = 0;//top是代表下一个位置需要插入的数head = 0;}int front(){int size = abs(tail - head);if (size == 0) return -1;else return p[head];//每次就是头部这里出去}int  push(int x){if ((tail+1)%mCapacity ==head)  //这代表满了{return -1;}else{p[tail] = x;tail = (tail + 1) % mCapacity;return 1;}}int pop(){if (head==tail)//空{return -1;}else{int ret = front();head = (head + 1) % mCapacity;return ret;}}int getsize(){return (tail-head+mCapacity)%mCapacity;}
};int main()
{quque  qu(5);for (int i=0;i<5;i++){qu.push(i);}cout << qu.getsize() << endl;;int n = qu.getsize();for (int i = 0;i < 100;i++){cout << "qu.getsize()=" << qu.getsize() << endl;int front = qu.pop();cout << front << endl;}}

链表实现队列(注意head指针实现 删除 tail指针实现插入,借助dummpy节点,需要需要注意的是当只有一个节点进行删除的时候,注意需要tail=front,防止丢失tail指针)

#include<iostream>
using namespace std;struct Node
{int data;struct Node *next;Node(){data = 0;next = nullptr;}Node(int x){data = x;next = nullptr;}
};struct  queue
{struct Node * head, *tail;queue(){head = new (Node);tail = head;cout << "...构造函数" << endl;}
};int push(queue  &que,int x)
{Node * newNode = new Node(x);que.tail->next = newNode;que.tail = que.tail->next;return -1;}int pop(queue  &que)
{int ret = -1;/*if (que.head!=que.tail)*///证明链中至少存在一个元素//cout << que.head->data << "    " << que.tail->data << endl;if (que.head != que.tail){ret = que.head->next->data;//100if (que.head->next->next==nullptr){que.head->next = que.head->next->next;que.tail = que.head;}else{que.head->next = que.head->next->next;}}else{cout << "我们发现相等啊" << endl;}return ret;
}int getsize(queue  que)
{Node * p = que.head->next;int size = 0;while (p!=NULL){p = p->next;size++;}return size;
}int main()
{queue  qu;for (int i=0;i<5;i++){push(qu, i);//cout << "getsize()=" << getsize(qu) << endl;}for (int i = 0;i < 10;i++){cout << "pop=" << pop(qu) << endl;}

题目2.1:

思路:
题目其实已经给出思路了

代码

#include<iostream>
#include<vector>
#include<queue>
using namespace std;class Solution {public:vector<int> deCode(vector<int>& nums) {vector<int> ret_v;queue<int> qu;for (int i=0;i<nums.size();i++){qu.push(nums[i]);}while (!qu.empty()){//将删除的元素放到 ret中ret_v.push_back(qu.front());qu.pop();if (!qu.empty()){// 然后将元素放到队列的尾端int front = qu.front();qu.pop();qu.push(front);}}return ret_v;}
};int main()
{vector<int> nums{ 6,3 ,1,7,5,8,9,2,4 };Solution s;vector<int> ret_v=s.deCode(nums);for (auto one: ret_v){cout << one << "  ";}
}

题目2.2

思路:

桌子上面的牌用vector保存
哼哈二将手中的牌用 队列保存就可以了。

需要注意一点 拖拉机里面的收牌加到尾部方式是,依次将弹出的牌加到尾部就可以了。

代码:

#include<iostream>
#include<vector>
#include<queue>
using namespace std;class Solution {private:void doLoad(vector<int> &restore, queue<int> &qu){int front = qu.front();qu.pop();auto it = find(restore.begin(), restore.end(), front);if (it != restore.end()){vector<int> append_v;append_v.push_back(front);//拖拉机里面的第一个数就是我们的front//需要弹出 将其补到restore的尾端int j = int(restore.size()) - 1;//避免无符号转换while (j >= 0 && restore[j] != front)//这里肯定能找到 restore[j]{append_v.push_back(restore[j]);restore.pop_back();//这个千万不要忘记j--;//不要忘记了}append_v.push_back(restore[j]);//这个是最后一个restore.pop_back();for (int val : append_v){qu.push(val);}}else{//直接加入到restore中restore.push_back(front);}}
public:/*返回true代表nums1会赢  否则false*/bool doTractor(vector<int>& nums1,vector<int>& nums2) {vector<int> restore;queue<int> qu1;for (auto value : nums1) qu1.push(value);queue<int> qu2;for (auto value : nums2) qu2.push(value);while (!qu1.empty()&&!qu2.empty()){cout << "qu1.size()=" << qu1.size() << "   qu2.size()=" << qu2.size() << "  restore.size()=" << restore.size() << endl;doLoad(restore, qu1);//先进行qu1的操作if (qu1.empty()) break;doLoad(restore, qu2);再进行qu2的操作if (qu2.empty()) break;}cout << "结果返回值" << endl;cout << "qu1.size()=" << qu1.size() << "   qu2.size()=" << qu2.size() << "  restore.size()=" << restore.size() << endl;if (!qu1.empty()){cout << "小哼赢了" << endl;while (!qu1.empty()){cout << "  " << qu1.front();qu1.pop();}cout << endl;cout << "桌子上面的牌" << endl;for (int val:restore){cout << "  " << val;}cout << endl;return true;}else{cout << "小哈赢了" << endl;while (!qu2.empty()){cout << "  " << qu2.front();qu2.pop();}cout << endl;cout << "桌子上面的牌" << endl;for (int val : restore){cout << "  " << val;}cout << endl;return false;}}
};int main()
{vector<int> nums1{ 2,4,1,2,5,6 };vector<int> nums2{3,1,3,5,6,4};Solution s;bool ret_b = s.doTractor(nums1, nums2);//cout << ret_b << endl;
}

我的代码运行结果

第三章

题目3.1

leetcode题目链接
题目
46. 全排列
给定一个 没有重复 数字的序列,返回其所有可能的全排列。

示例:

输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
思路:

dfs的思想,这里的index并不代表元素的下标,只是代表元素的个素,我习惯在dfs里面用index表示递归的深度。

代码:

class Solution {private:vector<vector<int>> ret_vv;void dfs(vector<int>& nums,vector<bool>& used,vector<int>& temp,int index){if(index>=nums.size()){ret_vv.push_back(temp);return;}for(int i=0;i<nums.size();i++){if(used[i]==true) continue;temp.push_back(nums[i]);used[i]=true;dfs(nums,used,temp,index+1);temp.pop_back();used[i]=false;}}
public:vector<vector<int>> permute(vector<int>& nums) {vector<bool> used(nums.size(),false);vector<int > temp;int index=0;dfs(nums,used,temp,index);return ret_vv;}
};

提升:
leetcode题目链接
47. 全排列 II
给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。

示例 1:

输入:nums = [1,1,2]
输出:
[[1,1,2],
[1,2,1],
[2,1,1]]
示例 2:

输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

思路:
我们可以发现此题与题目3.1只有一点不同,返回所有不重复的全排列。

这里面涉及到一个同一树层剪枝和树枝剪枝

方法一:同一树层(这个更快)

 if(i>0&&nums[i]==nums[i-1]&&isUse_v[i-1]==false) continue;

方法二:树枝剪枝

 if(i>0&&nums[i]==nums[i-1]&&isUse_v[i-1]==true) continue;

代码:

class Solution {private:void dfs(int index,vector<int>& nums,vector<bool> &isUse_v,vector<vector<int>> &result_vv,vector<int>&temp_v){if(index>=nums.size()){result_vv.push_back(temp_v);return;}for(int i=0;i<nums.size();i++){if(isUse_v[i]==true)  continue;if(i>0&&nums[i]==nums[i-1]&&isUse_v[i-1]==false) continue;temp_v.push_back(nums[i]);isUse_v[i]=true;dfs(index+1,nums,isUse_v,result_vv,temp_v);isUse_v[i]=false;temp_v.pop_back();}}public:vector<vector<int>> permuteUnique(vector<int>& nums) {vector<vector<int>>result_vv;vector<int>temp_v;vector<bool> isUse_v(nums.size(),false);sort(nums.begin(), nums.end());dfs(0,nums,isUse_v,result_vv,temp_v);return result_vv;}
};

第四章
题目4.1
全排列问题

思路:
dfs 上面题目3.1已经写过了。

代码:
同层剪枝(假设不能有重复的排列情况)

class Solution {private:void dfs(int index,vector<int>& nums,vector<bool> &isUse_v,vector<vector<int>> &result_vv,vector<int>&temp_v){if(index>=nums.size()){result_vv.push_back(temp_v);return;}for(int i=0;i<nums.size();i++){if(isUse_v[i]==true)  continue;if(i>0&&nums[i]==nums[i-1]&&isUse_v[i-1]==false) continue;temp_v.push_back(nums[i]);isUse_v[i]=true;dfs(index+1,nums,isUse_v,result_vv,temp_v);isUse_v[i]=false;temp_v.pop_back();}}public:vector<vector<int>> permuteUnique(vector<int>& nums) {vector<vector<int>>result_vv;vector<int>temp_v;vector<bool> isUse_v(nums.size(),false);sort(nums.begin(), nums.end());dfs(0,nums,isUse_v,result_vv,temp_v);return result_vv;}
};

题目4.2:

思路:
dfs,注意每次的递归终止条件是index>=nums.size()

A+B=C
最后的temp中 需要分离出 A,B,C

代码:

#include<iostream>
#include<vector>
using namespace std;class Solution {private:bool Compare(int temp){//A+B=C;int a[3];int i = 0;while (temp != 0){a[i] = temp % 1000;temp = temp / 1000;i++;}//A+B==C?if (a[2] + a[1] == a[0]){cout << a[2] << "+" << a[1] << "=" << a[0] << endl;return true;}else return false;}void dfs(vector<int>& nums, vector<bool>& used, int temp, int index ){if (index>= nums.size()){if (Compare(temp)) sum++;return;}for (int i=0;i<nums.size();i++){if (used[i] == true) continue;used[i] = true;dfs(nums, used, temp * 10 + nums[i], index+1);//千万要注意我们没有传 temp引用,ndex引用used[i] = false;}}int sum = 0;
public:int  permuteSumDiff(vector<int>& nums){int temp = 0;//这个是存每次递归的和int index = 0;vector<bool>  used(nums.size(),false);//标志位dfs(nums, used, temp,index );return sum;}
};
int main()
{vector<int> numbers{ 1,2,3,4,5,6,7,8,9 };Solution s;int sum=s.permuteSumDiff(numbers);cout << "sum=" << sum << endl;}

结果展示:

题目4.3
迷宫最短路径

思路:
其实这就是迷宫问题,由于我对于迷宫问题,喜欢将第一个点先拎出来,然后进行dfs

代码:


#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;class Solution {private:int global_step = INT_MAX;vector<vector<int>> dxy{ {0,1},{1,0},{0,-1}, {-1,0}};//走的方向依次是  右下左上bool isArea(vector<vector<int>> &maze,int temp_x,int temp_y){if (temp_x < 0 || temp_x >= maze.size() || temp_y < 0 || temp_y >= maze[0].size())  return false;return true;}void dfs(vector<vector<int>> &maze, vector<vector<bool>> &used,int current_i, int current_j, int target_i, int target_j, int &step){if (current_i == target_i&& current_j == target_j){global_step = min(global_step,step);return;}for (int i=0;i < dxy.size();i++){int temp_i = current_i + dxy[i][0];int temp_j = current_j + dxy[i][1];if (isArea(maze, temp_i, temp_j) && maze[temp_i][temp_j] == 0 &&used[temp_i][temp_j] == false){used[temp_i][temp_j] = true;step++;dfs(maze, used, temp_i, temp_j, target_i, target_j, step);step--;used[temp_i][temp_j] = false;}}}public:int getShortpath(vector<vector<int>> &maze, int start_i, int start_j, int target_i, int target_j)  //maze中0代表可走,1代表是障碍物{vector<vector<bool>> used(maze.size(), vector<bool>(maze[0].size(), false));if (isArea(maze, start_i, start_j) && used[start_i][start_j] == false)//这里防止刚开始位置越界{used[start_i][start_j] = true;int step = 0;dfs(maze, used, start_i,  start_j, target_i,  target_j, step);}return global_step;}
};int main()
{vector<vector<int>>  maze{{0,0,1,0},{0,0,0,0},{0,0,1,0},{0,1,0,0},{0,0,0,1} };int start_i = 0;int start_j = 0;int target_i = 3;int target_j = 2;Solution s;int path=s.getShortpath(maze, start_i, start_j, target_i, target_j);cout << "path=" << path << endl;
}

结果展示:

题目4.4
迷宫广度优先搜索

思路:
首先我们需要明确一点,在迷宫问题中采用bfs(广度优先遍历)会得到满足一个符合条件的。但可能不是最短路径。主要是进行迭代

代码:

#include<iostream>
#include<vector>
#include<queue>
using namespace std;#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;class Solution {private:vector<vector<int>> dxy{ {0,1},{1,0},{0,-1}, {-1,0} };//走的方向依次是  右下左上bool isArea(vector<vector<int>> &maze, int temp_x, int temp_y){if (temp_x < 0 || temp_x >= maze.size() || temp_y < 0 || temp_y >= maze[0].size())  return false;return true;}public:int getShortpath(vector<vector<int>> &maze, int start_i, int start_j, int target_i, int target_j)  //maze中0代表可走,1代表是障碍物{vector<vector<bool>> used(maze.size(), vector<bool>(maze[0].size(), false));if (isArea(maze, start_i, start_j) && used[start_i][start_j] == false)//这里防止刚开始位置越界{used[start_i][start_j] = true;int step = 0;queue<pair<int, int>> qu;qu.emplace(start_i, start_j);while (!qu.empty()){int n = qu.size();for (int i=0;i<n;i++){auto node = qu.front();qu.pop();//一定记得popint current_i = node.first;int current_j = node.second;//cout << "current_i=" << current_i << "  current_j=" << current_j  << "  step="<< step << endl;if (current_i == target_i && current_j == target_j){return  step;}for (int i = 0;i < dxy.size();i++){int temp_i = current_i + dxy[i][0];int temp_j = current_j + dxy[i][1];if (isArea(maze, temp_i, temp_j) &&maze[temp_i][temp_j]==0&& used[temp_i][temp_j] == false){cout << "temp_i=" << temp_i << "  temp_j=" << temp_j << "  step=" << step << endl;used[temp_i][temp_j] = true;qu.emplace(temp_i, temp_j);}}}cout << "*******************" << endl;for (int i=0;i<used.size();i++){for (int j = 0;j<used[0].size();j++){cout << used[i][j] << "  ";}cout << endl;}cout << endl;cout << "*******************" << endl;step++;}}return INT_MAX;}
};int main()
{vector<vector<int>>  maze{{0,0,1,0},{0,0,0,0},{0,0,1,0},{0,1,0,0},{0,0,0,1} };int start_i = 0;int start_j = 0;int target_i = 3;int target_j = 2;Solution s;int path = s.getShortpath(maze, start_i, start_j, target_i, target_j);cout << "path=" << path << endl;}

题目4.5

思路递归过程中用floodfill方法,其实就是used[i][j]=true后,不在进行恢复,减少重复操作,然后在每个合格点再进行判断消除的怪兽数目,保存可以消灭怪兽的最多数

代码:略

题目4.6

floodfilld应用

求飞机降落点中的岛屿快的总面积

思路:
我是比较喜欢
代码:

#include<iostream>
#include<vector>using namespace std;class Solution {private:vector<vector<int>> dxy{ {0,1},{1,0},{0,-1}, {-1,0} };//走的方向依次是  右下左上bool  isArea(vector<vector<int>>& grid, int temp_i, int temp_j){if (temp_i < 0 || temp_i >= grid.size() || temp_j < 0 || temp_j >= grid[0].size())  return false;return true;}int s = 0;//这个是可以这样进行赋值的void dfs(vector<vector<int>>&grid, vector<vector<bool>>& used, int current_i, int current_j){for (int i = 0;i < dxy.size();i++){int temp_i = current_i + dxy[i][0];int temp_j = current_j + dxy[i][1];if (isArea(grid, temp_i, temp_j) && grid[temp_i][temp_j] > 0 && used[temp_i][temp_j] == false){used[temp_i][temp_j] = true;s++;grid[temp_i][temp_j] = s;dfs(grid, used, temp_i, temp_j);//used[temp_i][temp_j] = false;  floodfill 就是不要这句话}}}
public:int islandArea(vector<vector<int>>& grid,int start_i,int start_j){vector<vector<bool>> used(grid.size(), vector<bool>(grid[0].size(), false));if (isArea(grid,start_i,start_j)&&used[start_i][start_j]==false){if (grid[start_i][start_j] > 0){used[start_i][start_j] = true;s++;grid[start_i][start_j] = s;dfs(grid, used, start_i, start_j);}}cout << "*******************" << endl;for (int i = 0;i < grid.size();i++){for (int j = 0;j < grid[0].size();j++){//cout << grid[i][j] << "     ";printf("%5d", grid[i][j]);}cout << endl;}cout << endl;cout << "*******************" << endl;return s;}
};int main()
{vector<vector<int>>  maze{{1,2,1,0,0,0,0,0,2,3},{3,0,2,0,1,2,1,0,1,2},{4,0,1,0,1,2,3,2,0,1},{3,2,0,0,0,1,2,4,0,0},{0,0,0,0,0,0,1,5,3,0},{0,1,2,1,0,1,5,4,3,0},{0,1,2,3,1,3,6,2,1,0}, {0,0,3,4,8,9,7,5,0,0}, {0,0,0,3,7,8,6,0,1,2}, {0,0,0,0,0,0,0,0,1,0}, };int start_i = 5;int start_j = 7;Solution s;int sum = s.islandArea(maze, start_i, start_j);cout << "sum=" << sum << endl;
}

运行结果
我们可以看到floodfill的运行效果截图,

题目4.7


leetcode200. 岛屿数量
题目:

思路:
floodfill,相比较题目4.6而言,需要在main函数中套上循环遍历grid

代码:

class Solution {private:vector<vector<int>> dxy{ {0,1},{1,0},{0,-1}, {-1,0} };//走的方向依次是  右下左上bool  isArea(vector<vector<char>>& grid, int temp_i, int temp_j){if (temp_i < 0 || temp_i >= grid.size() || temp_j < 0 || temp_j >= grid[0].size())  return false;return true;}int count = 0;//这个是可以这样进行赋值的void dfs(vector<vector<char>>&grid, vector<vector<bool>>& used, int current_i, int current_j){for (int i = 0;i < dxy.size();i++){int temp_i = current_i + dxy[i][0];int temp_j = current_j + dxy[i][1];if (isArea(grid, temp_i, temp_j) && grid[temp_i][temp_j] !='0' && used[temp_i][temp_j] == false){used[temp_i][temp_j] = true;dfs(grid, used, temp_i, temp_j);//used[temp_i][temp_j] = false;  floodfill 就是不要这句话}}}
public:int numIslands(vector<vector<char>>& grid){vector<vector<bool>> used(grid.size(), vector<bool>(grid[0].size(), false));for (int start_i=0;start_i<grid.size();start_i++){for (int start_j = 0;start_j < grid[0].size();start_j++){if (isArea(grid, start_i, start_j) && used[start_i][start_j] == false){if (grid[start_i][start_j] != '0'){used[start_i][start_j] = true;count++;dfs(grid, used, start_i, start_j);}}}}return count;}
};

题目4.8

思路:
这题首先从start_i=0,start_j=0出开始找路,所以第一个水管是
中形状,然后采用dfs看有没够水管能够与第一个水管接上的,接上了就继续dfs,依次寻找,直到到达出口,当某一个水管接不上时,如果无论怎么旋转方向都不满足,回溯,转换当前不满足水管的方向,如果还是不满足,那么就可以后退一个,再次判定,代码中也是需要used判断水管位置的访问状态的

代码:

第五章:
图论

第六章
最短路径

题目:求某个点到某个结束点的最短路径

其实这个问题涉及到的问题很广,实用性贼强,下面介绍三个算法
游戏中寻路算法
6.1.1方法一:广度优先搜索算法
//bfs寻路算法 确定也明显 没有像 迪杰斯特拉算法中的最短路径一样。也就是没有权值不能找到最短的

代码

//bfs寻路算法  确定也明显 没有像 迪杰斯特拉算法中的最短路径一样。也就是没有权值,不能找到最短的//used[temp_i][temp_j] = true;  bfs没有对应的 false这是和bfs不一样的
#include<iostream>
#include<vector>
#include<queue>
using namespace std;#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;class Solution {private:vector<vector<int>> dxy{ {0,1},{1,0},{0,-1}, {-1,0} };//走的方向依次是  右下左上bool isArea(vector<vector<int>> &maze, int temp_x, int temp_y){if (temp_x < 0 || temp_x >= maze.size() || temp_y < 0 || temp_y >= maze[0].size())  return false;return true;}public:int getShortpath(vector<vector<int>> &maze, int start_i, int start_j, int target_i, int target_j)  //maze中0代表可走,1代表是障碍物{vector<vector<bool>> used(maze.size(), vector<bool>(maze[0].size(), false));if (isArea(maze, start_i, start_j) && used[start_i][start_j] == false)//这里防止刚开始位置越界{used[start_i][start_j] = true;int step = 0;queue<pair<int, int>> qu;qu.emplace(start_i, start_j);while (!qu.empty()){int n = qu.size();for (int i = 0;i < n;i++){auto node = qu.front();qu.pop();//一定记得popint current_i = node.first;int current_j = node.second;//cout << "current_i=" << current_i << "  current_j=" << current_j  << "  step="<< step << endl;if (current_i == target_i && current_j == target_j){return  step;}for (int i = 0;i < dxy.size();i++){int temp_i = current_i + dxy[i][0];int temp_j = current_j + dxy[i][1];if (isArea(maze, temp_i, temp_j) && maze[temp_i][temp_j] == 0 && used[temp_i][temp_j] == false){cout << "temp_i=" << temp_i << "  temp_j=" << temp_j << "  step=" << step << endl;used[temp_i][temp_j] = true;qu.emplace(temp_i, temp_j);}}}cout << "*******************" << endl;for (int i = 0;i < used.size();i++){for (int j = 0;j < used[0].size();j++){cout << used[i][j] << "  ";}cout << endl;}cout << endl;cout << "*******************" << endl;step++;}}return INT_MAX;}
};int main()
{vector<vector<int>>  maze{{0,0,1,0},{0,0,0,0},{0,0,1,0},{0,1,0,0},{0,0,0,1} };int start_i = 0;int start_j = 0;int target_i = 3;int target_j = 2;Solution s;int path = s.getShortpath(maze, start_i, start_j, target_i, target_j);cout << "path=" << path << endl;}

题目:
6.1.2迪杰斯特拉算法 可以找到所有的节点最短路径,
求以某一起始点到另外所有结点的最短路径dist

思路:

首先对应的二维矩阵是

其次我们需要明白 迪杰斯特拉(Dijkstra)是针对连通图来说的。
代码最重要的两个变量

     vector<int> visit(n,0);//0代表未访问节点,1代表访问节点vector<int> dist(n, 0);//后面会根据start进行初始化,这里初始化值是任何值都没关系

主要思路是,首先将start节点先拎出来,然后每次将最小的dist的没有访问的节点找到作为中转节点,然后以中转节点更新,dist的从起始节点到非访问节点的更小值。
代码:

//单源最短路径,迪杰斯特拉算法//总体思路,是将每次最短的还没有访问的节点作为中转节点,然后从寻找从中转节点到其他节点和之前的到start的节点路径作比较,
//更新每个未访问节点的最短路径,将中转节点设置成访问节点,进入下一次循环。
#include<iostream>
#include<vector>#define INF  999999//路径中不可达边  因此graph也应该这么写不可达边的长度using namespace std;class Solution {public:vector<int> Dijkstra(vector<vector<int>>& graph,int start){int n = graph.size();vector<int> visit(n,0);//0代表未访问节点,1代表访问节点vector<int> dist(n, 0);//后面会根据start进行初始化,这里初始化值是任何值都没关系//首先将第一个start节点的信息提取出来,为循环做出准备if (start>=n){cout << "起点位置不合法" << endl;return  dist;}visit[start] = 1;//  设置起点位置已访问1for (int i=0;i<n;i++)//设置起点位置为初始位置,初始化dist{dist[i] = graph[start][i];}for (int i=1;i<n;i++)//第一个节点已经单独拎出来了个节点,所以我们需要循环n-1次{int minNumber = INF;int mind=1111;//我们从这里可以看出无论此处mind初始值是多少,如果不是连通图,可能会造成,死循环, 因此使用该算法的图应该是连通图 for (int j=0;j< dist.size();j++)//寻找中转节点  记住当前中转节点一定是未访问节点{if (visit[j]==0&& minNumber> dist[j]){minNumber = dist[j];mind = j;}}//cout << "mind=" << mind << endl;//visit[mind] = 1;  //这个放在这里也是可以的//中转节点找到后,我们需要更新当前以中转节点和原点的  到其他非访问节点距离  for (int j=0;j<n;j++)//这里的j代表着节点的下标的意思{if (visit[j]==0&&dist[j]>dist[mind]+graph[mind][j])//这一步说明了graph中不能有INT_MAX不然可能会溢出{dist[j] = dist[mind] + graph[mind][j];}}visit[mind] = 1;//应该将中转节点设置成已访问}return dist;}
};int main()
{int n = 6;vector<vector<int>> graph(n, vector<int>(n, INF));for (int i=0;i<n;i++){graph[i][i] = 0;}graph[0][1] = 100;graph[1][0] = 100;graph[0][2] = 1200;graph[2][0] = 1200;graph[1][2] = 900;graph[2][1] = 900;graph[1][3] = 300;graph[3][1] = 300;graph[2][3] = 400;graph[3][2] = 400;graph[2][4] = 500;graph[4][2] = 500;graph[3][4] = 1300;graph[4][3] = 1300;graph[3][5] = 1400;graph[5][3] = 1400;graph[4][5] = 1500;graph[5][4] = 1500;Solution s;vector<int> dist;for (int j=0;j<n;j++){cout << "以索引值为start=" << j << "设置为起始点" << endl;dist = s.Dijkstra(graph, j);for (int i = 0;i < n;i++){cout << "  " << dist[i];}cout << endl;}}

结果:

缺点:
迪杰斯特拉算法在寻路的网格中是无目的性的,(因为我们将每个节点的最短路径都找出来了,而不是找起点到给定终点的最短路径)

6.1.3方式三:A*算法视频参考链接
**A*算法,**可以确定最短路径(总代价最小) 总代价=当前代价+预估代价

当前代价:我们可以使用 当前位置到起点位置的步数
预估代价,说明不是一个确切的数字,我们可以使用 曼哈顿距离 表示当前位置和目标位置 这两个坐标的绝对值差的和 即|x1-x2|+|y1-y2|

思路:
总代价=当前代价+预估代价 我们每次将当前的节点的总代价,加入到优先队列priority_queue(注意,我们需要重写仿函数 从cmp,使得堆顶最小),

struce  cmp
{operator()(node1,node2){return node1.step_cost+node1.cost_so_far>node2.step_cost+node2.cost_so_far}
]

代码:
待定

第七章

题目7.1
leetcode排序链接
堆排序

思路:
用数据实现堆排序

进行堆排序输出的过程其实可以看做是删除堆顶元素的重复的过程
堆排序输出

     vector<int> temp_v = nums;//进行堆排序输出//大根堆建好后,开始进行堆顶元素cout << "堆排序后的数组逻辑为" << endl;for (int i=n-1;i>=0;i--)//这其实可以看做是一个删除的过程{swap(temp_v[0], temp_v[i]);sortHeap(temp_v, 0, i);//每次将最后一个位置确定后,循环n次1,这样数组就是有序的}

删除堆顶元素

void pop(vector<int>& nums){int n = nums.size();swap(nums[0], nums[n - 1]);cout << "删除的栈顶元素是" << nums.back() << endl;nums.pop_back();n = nums.size();//nums中已经删除一个元素了。因此需要重新取大小sortHeap(nums, 0, n);}

代码:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;class Solution {private:void sortHeap(vector<int>& nums,int index, int n)//我们需要建立大根堆{int max = index;int left_index = index * 2 + 1;int right_index = index * 2 + 2;if (left_index<n&&nums[left_index]>nums[max]){max = left_index;}if (right_index<n&&nums[right_index]>nums[max]){max = right_index;}if (max != index){swap(nums[max],nums[index]);sortHeap(nums, max, n);//这是一个下溯的过程}}
public:vector<int> Heap(vector<int>& nums) {int n = nums.size();for (int index=n/2-1;index >=0;index--)  //index代表着我们的需要比对的初始化的数字的位置(上溯过程){sortHeap(nums, index, n);}vector<int> temp_v = nums;//进行堆排序输出//大根堆建好后,开始进行堆顶元素cout << "堆排序后的数组逻辑为" << endl;for (int i=n-1;i>=0;i--)//这其实可以看做是一个删除的过程{swap(temp_v[0], temp_v[i]);sortHeap(temp_v, 0, i);//每次将最后一个位置确定后,循环n次1,这样数组就是有序的}//cout << endl;return temp_v;}//插入void insert(vector<int>& nums,int x){nums.push_back(x);int n = nums.size();for (int index = n / 2 - 1;index >= 0;index--)  //index代表着我们的需要比对的初始化的数字的位置(上溯过程){sortHeap(nums, index, n);}}//删除元素void pop(vector<int>& nums){int n = nums.size();swap(nums[0], nums[n - 1]);cout << "删除的栈顶元素是" << nums.back() << endl;nums.pop_back();n = nums.size();//nums中已经删除一个元素了。因此需要重新取大小sortHeap(nums, 0, n);}};int main()
{vector<int> nums{ 4,6,2,3,5,8,6,9,4,1,6 };Solution s;vector<int> ret=s.Heap(nums);for (int value:ret){cout << "   " << value;}cout << endl;int n = nums.size();for (int i=0;i<n;i++){s.pop(nums);}s.insert(nums,5);s.insert(nums,4);s.insert(nums,10);n = nums.size();cout << "插入元素后重新删除" << endl;for (int i = 0;i < n;i++){s.pop(nums);}
}

运行结果

题目7.2
leetcode 684链接
确认图中有没有环
思路:

代码:


#include <iostream>
#include<algorithm>
#include<vector>
using namespace std;const int MAXN = 1e6 + 10;
int parent[MAXN], RANK[MAXN];void Init()
{for (int i=0;i< MAXN;i++){parent[i] = i;RANK[i] = 1;}
}
//寻找x的头部(非递归写法)
int  Find(int x)
{int x_root = x;while (parent[x_root]!= x_root){x_root = parent[x_root];}return x_root;
}寻找x的头部(递归写法)
//int  Find(int x)
//{//
//  if (parent[x] == x)
//  {//      return x;
//  }
//  return Find(parent[x]);
//}int Union(int u, int v)
{u = Find(u);v = Find(v);if (u != v){if (RANK[u] > RANK[v] ){parent[v] = u;}else if(RANK[v] > RANK[u]){parent[u] = v;}else if (RANK[v]= RANK[u]){parent[v] = u;RANK[u]++;}return 1;}else{return 0;}}
int main()
{Init();vector<vector<int>> vv{ {0,1},{1,2},{1,3},{2,5},{2,4},{3,4}};for (int i=0;i< vv.size();i++){int u = vv[i][0];int v = vv[i][1];if (Union(u, v) == 0){cout << " 图中存在环" << endl;return 0;}}cout << " 图中不存在环" << endl;return 1;
}

啊哈!算法 案例用c++实现相关推荐

  1. spark 随机森林算法案例实战

    随机森林算法 由多个决策树构成的森林,算法分类结果由这些决策树投票得到,决策树在生成的过程当中分别在行方向和列方向上添加随机过程,行方向上构建决策树时采用放回抽样(bootstraping)得到训练数 ...

  2. 转盘抽奖php,使用PHP实现转盘抽奖算法案例解析

    这次给大家带来使用PHP实现转盘抽奖算法案例解析,使用PHP实现转盘抽奖算法的注意事项有哪些,下面就是实战案例,一起来看一下. 流程: 1.拼装奖项数组 2.计算概率 3.返回中奖情况 代码如下: 中 ...

  3. ML之LoR:利用LoR二分类之非线性决策算法案例应用之划分正负样本

    ML之LoR:利用LoR二分类之非线性决策算法案例应用之划分正负样本 目录 输出结果 实现代码 输出结果 1.对数据集进行特征映射 2.正则化 → 正则化 → 过度正则化 实现代码 import nu ...

  4. python编程思维代码_Python编程快速上手——强口令检测算法案例分析

    本文实例讲述了Python强口令检测算法.分享给大家供大家参考,具体如下: 强口令检测 题目如下: 写一个函数,它使用正则表达式,确保传入的口令字符串是强口令.强口令定义:长度不少于8个字符,同时包含 ...

  5. php分割金额_PHP实现红包金额拆分算法案例详解

    这次给大家带来PHP实现红包金额拆分算法案例详解,PHP实现红包金额拆分算法的注意事项有哪些,下面就是实战案例,一起来看一下.<?php // 新年红包金额拆分试玩 class CBonus { ...

  6. 随机森林的java算法_spark 随机森林算法案例实战

    随机森林算法 由多个决策树构成的森林,算法分类结果由这些决策树投票得到,决策树在生成的过程当中分别在行方向和列方向上添加随机过程,行方向上构建决策树时采用放回抽样(bootstraping)得到训练数 ...

  7. 《经典算法案例》01-10:如何打印质数表(六列版)

      <经典算法案例> 01-10:如何打印质数表(六列版) 本文通过表格的形式罗列出了0~9999的自然数,以及在此区间内的所有质数,方便大家观察和研究. 提示:源码在文章末尾. 1.图示 ...

  8. 《经典算法案例》01-09:如何打印质数表(十列版)

    <经典算法案例> 01-09:如何打印质数表(十列版) 本文通过表格的形式罗列出了0~9999的自然数,以及在此区间内的所有质数,方便大家观察和研究. 提示:源码在文章末尾. 1.图示法 ...

  9. 《经典算法案例》:听英文神曲不误算法

      <经典算法案例> 听英文神曲不误算法   <Faded>是一首以电音的基本旋律作为主体辅乐的曲子,在经过原艾兰·沃克作者的调和下融入了空灵的女声,使得电音的旋律在女声的演绎 ...

  10. 高中计算机辗转相除法,高三数学教案:算法案例――辗转相除法

    <高三数学教案:算法案例――辗转相除法>由会员分享,可在线阅读,更多相关<高三数学教案:算法案例――辗转相除法(7页珍藏版)>请在人人文库网上搜索. 1.算法案例 辗转相除法育 ...

最新文章

  1. 数据结构实验——中缀表达式转为后缀表达式
  2. 网络正常,但是网络图标上有黄色的三角图标
  3. mysql搜索_mysql 几种搜索引擎的比较
  4. 卷成这样,非逼我用RTX 3090?(深度学习GPU平台种草
  5. 解密诡异并发问题的幕后黑手:可见性问题
  6. Cobra命令行框架及使用
  7. java_opts gc回收器_jvm垃圾收集器与内存分配策略
  8. “赤膊贪凉”要不得 多喝蜜水防“秋燥”
  9. android中fragment如何保存edittext文本,如何在Android中使用DialogFragment进行文本输入?...
  10. 咖啡口味介绍及存储方式
  11. spring5.0学习笔记8
  12. 多指标评价方法-变异系数法的pathon实现
  13. js获取时分秒数据格式为YYYMMDDHHmm方法
  14. 【Apache Spark 】第 2 章下载 Apache Spark并开始使用
  15. 壹佰大米时代公司研究报告
  16. 嵌入式linux platform设备驱动
  17. networkx笔记
  18. Vue定时器设置 Vue简单定时任务
  19. ajax和flash,flask ajax请求后flash方法(消息闪现)无效问题的解决方法
  20. 100款现代科技感的英文字体打包分享

热门文章

  1. 最近看过的几本给我印象深刻的书
  2. 开办公司的流程(四川)
  3. 群晖双网口虚拟机openwrt主路由二级路由拨号上网配置
  4. 三十而立技术er的进击之路
  5. 贴片电阻丝印是什么意思
  6. Linux下挂载u盘和光盘,即移动存储设备
  7. 得到最好的两个worlds-让Android应用程序运行在PC上
  8. 文语通5.0破解版安装说明
  9. ubuntu安装anaconda报错:Cannot open xxx/anaconda3/conda.exe or archive xxx/anaconda3/conda.exe.pkg
  10. 南阳师范学院大一计算机老师,大学计算机A