Alg | NWPU 头歌1-1 二分查找

文章讲述了作者在分析一个简单的搜索函数时,比较了使用if-else递归结构与while循环的两种实现方式,强调了递归分治思想的应用,并自嘲因混淆二者导致的困扰,提倡多练习提升编程技能。

一个这么简单的代码居然掰扯了好久,分析判断了好一会才发现了问题所在。

void search(int start, int end)
{
	if (end - start > 0)
	{
		int mid = (end + start) / 2;
		if (num[mid] == k)
		{
			flag = 1;
		}
		if (num[mid] > k)
		{
			search(start, mid);
		}
		if (num[mid] < k)
		{
			search(mid+1, end);
		}
	}
	return;
}

要么就这么写,用if判断一下还能不能再往下走;要么就:

void search(int start, int end)
{
	while(end - start >= 0)
	{
		int mid = (end + start) / 2;
		if (num[mid] == k)
		{
			flag = 1;
			return ;
		}
		if (num[mid] > k)
		{
			end = mid - 1;
		}
		if (num[mid] < k)
		{
			start = mid + 1;
		}
	}
	return;
}

要么就用while语句循环,并不断更新start和end的值。

说实话感觉前者更加符合递归分治的定义。

而我,把这俩给混在一起了,又用while又函数嵌套......菜就多练

请根据程序提示完成相功能,包括读取文件data.txt信息创建图的邻接表,输出图的相信息,输出图的所有顶点的入度和出度。 【输入文件样例】 5 8 //顶点数和边数 V0 V1 V2 V3 V4 //顶点值 V0 V1 //第一条边 V0 V3 //第二条边 V0 V4 V1 V2 V1 V3 V2 V3 V2 V4 V3 V4 【输出样例】 有向图有5个顶点,8条边。 邻接表为: |0|V0|->|4|V4|->|3|V3|->|1|V1| |1|V1|->|3|V3|->|2|V2| |2|V2|->|4|V4|->|3|V3| |3|V3|->|4|V4| |4|V4| 顶点V0的入度和出度分别为:0, 3 顶点V1的入度和出度分别为:1, 2 顶点V2的入度和出度分别为:1, 2 顶点V3的入度和出度分别为:3, 1 顶点V4的入度和出度分别为:3, 0#include<iostream> #include<string> #include<fstream> using namespace std; const int MAX = 20; //顶点结点 struct HNode { string data;//结点值 int no;//结点编号 HNode* next;//邻接点 }; //邻接表 struct ALGraph { int n, e;//顶点数,边数 HNode hnode[MAX]; }; //在顶点集中查找指定结点值的结点编号 int IndexOfHNode(HNode* node, string s, int n) { } //有向图 class Graph { public: Graph();//构造函数 ~Graph();//析构函数 void CreateALGraph();//读入文件data.txt创建图的邻接表 void DisplayALGraph();//输出图相信息 int InDegreeOfNode(string);//计算某个顶点的入度 int OutDegreeOfNode(string);//计算某个顶点的出度 void AllDegree();//输出所有顶点的度 private: ALGraph* alg; }; int main() { Graph graph; graph.CreateALGraph(); graph.DisplayALGraph(); graph.AllDegree(); return 0; }
05-28
### 实现方案 根据问题描述,可以使用C++实现一个程序,通过读取`data.txt`文件构建图的邻接表,并输出图的基本信息(如顶点数、边数)、邻接表内容以及每个顶点的入度和出度。以下是具体的实现方法: #### 1. 文件格式假设 假设`data.txt`文件的内容如下: - 第一行包含两个整数:顶点数`vlen`和边数`elen`。 - 接下来的`vlen`行表示顶点的名称。 - 最后的`elen`行表示边的连接系(每行两个顶点名)。 例如: ``` 4 4 A B C D A B B C C D D A ``` #### 2. 邻接表的定义 邻接表的结构可以通过以下类实现[^1]: ```cpp #include <iostream> #include <fstream> #include <vector> #include <unordered_map> using namespace std; #define MAX 100 class ENode { public: int ivex; // 该边所指向的顶点的位置 ENode *nextEdge; // 指向下一条弧的指针 }; class VNode { public: char data; // 顶点信息 ENode *firstEdge; // 指向第一条依附该顶点的弧 }; class ListUDG { private: int mVexNum; // 图的顶点的数目 int mEdgNum; // 图的边的数目 VNode mVexs[MAX]; // 顶点数组 unordered_map<char, int> vertexMap; // 顶点字符到索引的映射 public: ListUDG() : mVexNum(0), mEdgNum(0) {} ~ListUDG(); void createGraph(const vector<string>& vexs, const vector<pair<char, char>>& edges); void print(); void calculateInOutDegree(); }; ``` #### 3. 构建图 通过读取文件并解析数据,调用`createGraph`方法构建图的邻接表[^2]: ```cpp void ListUDG::createGraph(const vector<string>& vexs, const vector<pair<char, char>>& edges) { // 初始化顶点 for (int i = 0; i < vexs.size(); ++i) { mVexs[i].data = vexs[i][0]; mVexs[i].firstEdge = nullptr; vertexMap[mVexs[i].data] = i; } mVexNum = vexs.size(); // 添加边 for (const auto& edge : edges) { char v1 = edge.first; char v2 = edge.second; if (vertexMap.find(v1) == vertexMap.end() || vertexMap.find(v2) == vertexMap.end()) { continue; // 跳过无效顶点 } int p1 = vertexMap[v1]; int p2 = vertexMap[v2]; // 创建边节点 ENode* newNode = new ENode(); newNode->ivex = p2; newNode->nextEdge = mVexs[p1].firstEdge; mVexs[p1].firstEdge = newNode; // 如果是无向图,需要反向添加边 ENode* reverseNode = new ENode(); reverseNode->ivex = p1; reverseNode->nextEdge = mVexs[p2].firstEdge; mVexs[p2].firstEdge = reverseNode; mEdgNum++; } } ``` #### 4. 输出邻接表 通过遍历邻接表,输出图的相信息: ```cpp void ListUDG::print() { cout << "邻接表内容:" << endl; for (int i = 0; i < mVexNum; ++i) { cout << mVexs[i].data << ": "; ENode* node = mVexs[i].firstEdge; while (node != nullptr) { cout << mVexs[node->ivex].data << " "; node = node->nextEdge; } cout << endl; } cout << "顶点数: " << mVexNum << ", 边数: " << mEdgNum << endl; } ``` #### 5. 计算入度与出度 通过遍历邻接表计算每个顶点的入度和出度[^3]: ```cpp void ListUDG::calculateInOutDegree() { vector<int> inDegree(mVexNum, 0); vector<int> outDegree(mVexNum, 0); for (int i = 0; i < mVexNum; ++i) { ENode* node = mVexs[i].firstEdge; while (node != nullptr) { outDegree[i]++; inDegree[node->ivex]++; node = node->nextEdge; } } cout << "顶点入度与出度:" << endl; for (int i = 0; i < mVexNum; ++i) { cout << mVexs[i].data << " - 入度: " << inDegree[i] << ", 出度: " << outDegree[i] << endl; } } ``` #### 6. 主函数实现 读取文件并调用相方法: ```cpp int main() { ifstream fin("data.txt"); if (!fin.is_open()) { cerr << "无法打开文件" << endl; return -1; } int vlen, elen; fin >> vlen >> elen; vector<string> vexs(vlen); for (int i = 0; i < vlen; ++i) { fin >> vexs[i]; } vector<pair<char, char>> edges(elen); for (int i = 0; i < elen; ++i) { char v1, v2; fin >> v1 >> v2; edges[i] = make_pair(v1, v2); } fin.close(); ListUDG graph; graph.createGraph(vexs, edges); graph.print(); graph.calculateInOutDegree(); return 0; } ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值