final review outline

review outline

 

Question types: 3 programming questions, 4 comprehensive questions.

1. Programming questions:

1. The type definition of the linked list; the type definition of the graph represented by the adjacency matrix; the type definition of the graph represented by the linked list; the definition and usage method of the graph represented by the vector array.

2. Insertion and deletion operations of nodes in the linked list, time complexity analysis.

3. The calculation method of the connected components of the graph: DFS, BFS and union search.

4. The realization principle and method of binary search based on ordered sequence, time complexity analysis.

2. Comprehensive questions

Including aspects such as drawing, calculation and algorithm description.

1. The structure diagram of the generalized table and the header, footer, table length and depth of the generalized table.

2. The construction steps and construction process of the Huffman tree and the calculation method of the weighted path length.

3. The general steps of the minimum spanning tree (Kruskal algorithm, Prim algorithm). There is a procedure for generating a minimum spanning tree from a graph.

4. The general steps of inserting and deleting a key value in a binary search tree, the process of generating a binary search tree from a key value sequence, and the process of deleting a key value in a binary search tree.

Note: The test questions are all from the exercises in the textbook, but the data and requirements of some questions will be adjusted appropriately.

Full knowledge of linked list: (1 message) Here comes the detailed explanation of linked list

1. Programming questions:

1. Type definition of linked list;

typedef struct clNode {
	datatype data; //数据域
	clNode* next; //链域
	clNode() :next(NULL) {
		data = 0;
	}
}*chainList;

Adjacency matrix representation graph type definition;

struct adjMatrix {
	datatype data[eNum]; //顶点的数据信息
	int edge[eNum][eNum];//邻接矩阵
	int v; //顶点的数量
	int e; //边的数量
};

The link table represents the type definition of the graph;

struct vertex {
	int u; //邻接点的编号
	int w; //权重,无权图可忽视该属性
	vertex* next;
	vertex(int u1=0,int w1=0):u(u1),w(w1),next(NULL){}
};
 
typedef struct llNode {
	datatype data[vNum]; //顶点的数据信息
	vertex* edges[vNum]; //边表
	int v, e; //顶点数和边数
	llNode() :v(0), e(0) {
		for (int i = 0; i < vNum; i++)
			edges[i] = NULL;
	}
}*linkList;

The vector array represents the definition and usage of the graph.

//图的vector数组表示的类型定义
struct edge {
	int v; //邻接点
	int w; //权重,无权图可忽视该属性
	edge(int v1, int w1) :v(v1), w(w1) {};
};

typedef struct vgNode {
	vector<edge>edges[vNum]; //边表
	datatype data[vNum]; //顶点的数据信息
	int v, e; //顶点数和边数
}vecGraph;
 
//创建vector数组表示的图
void create_vecGraph(vecGraph& g) {
	int i, u, v, w;
	cin >> g.v >> g.e; //输入顶点数和边数
	for (i = 0; i < g.e; i++) {
		cin >> u >> v >> w; //输入边的信息,无权图省略w,且下列语句w变为1
		g.edges[u].push_back(edge(v, w)); //将边(u,v)加入图中
		g.edges[v].push_back(edge(u, w)); //将边(v,u)加入图中,有向图忽略该语句
	}
}
 
//在实际应用中,可以采取如下更简单的表示方法
int v; //顶点数
vector<int>g[vNum]; //无权图
vector<pair<int, int>>g1[vNum]; //有权图,pair中的first代表邻接点,second代表权重

2. Insertion and deletion operations of nodes in the linked list, time complexity analysis.

void cl_insert(chainList p, datatype x)
{
	chainList q = new clNode;//定义新的结点,用指针指向新定义的指针
	//判断是否有足够的空闲存储空间存放新结点
	if (q == NULL)
	{
		cout << "插入结点失败!" << endl;
		return;
	}
	q->data = x;
	q->next = p->next;
	p->next = q;
}
//查询循环链表中是否存在值为x的结点
chainList rcl_search(chainList h, datatype x)
{
	if (h == NULL) return NULL;
	chainList h1 = h;
	do {
		h1 = h1->next;
		if (h1->data == x)return h1;
	} while (h1 != h);
	return NULL;
}

void cl_delete(chainList h, datatype x)
{
	chainList p = new clNode;
	p = cl_search(h, x);
	if (p == NULL)return;
	chainList q = p->next;
	if (q == NULL)return;
	p->next = q->next;
	delete q; //释放了q所占用的空间,但q指针仍有指向
	q = NULL; //设置为空指针
}

3. The calculation method of the connected components of the graph: DFS, BFS and union search.

DFS:

#include<iostream>
#include<vector>
using namespace std;
constexpr auto eNum = 102; //图的顶点数量
constexpr auto vNum = 200; //图的边的数量
typedef string dataType; //图顶点中存放数据信息的类型
typedef int datatype;
constexpr auto INF = 0x3f3f3f3f;
 
//图的深度优先搜索,以下模板基于vector数组所表示的图(有向图/无向图)
bool vis[vNum]; //标记每一个顶点的颜色
int dfn[vNum], cnt = 0; //dfn存放DFS序列,cnt为序列的编号
//对图g的顶点cur所在的连通分量进行深度优先搜索,初始出发顶点为cur
void dfs(vector<datatype>g[vNum], int cur) {
	int i, u;
	dfn[++cnt] = cur; //将当前顶点cur的深度优先编号为cnt
	vis[cur] = true; //将当前顶点涂为黑色
	for (i = 0; i < g[cur].size(); i++) { //检查cur的每一个邻接点
		u = g[cur][i]; 
		if (!vis[u]) //u为白色,(cur,u)为树边
			dfs(g, u); //从u出发继续搜索
	}
}
 
//对图g进行深度优先搜索,v为顶点的数量
void dfs_traverse(vector<int>g[vNum], int v) {
	int i;
	memset(vis, 0, sizeof(vis)); //将每个顶点都设置为白色
	for (i = 1; i <= v; i++)
		if (!vis[i]) //如果存在白色顶点,则从该顶点出发进行深度优先搜索
			dfs(g, i);
}
 
int main() {
 
}

BFS:

#include<iostream>
#include<vector>
#include<queue>
using namespace std;
constexpr auto eNum = 102; //图的顶点数量
constexpr auto vNum = 200; //图的边的数量
typedef string dataType; //图顶点中存放数据信息的类型
typedef int datatype;
constexpr auto INF = 0x3f3f3f3f;
 
bool vis[vNum]; //标记顶点的颜色
int bfn[vNum]; //广度优先序列
//对图g中cur所在的连通分量进行广度优先搜索,初始出发点为cur
void bfs(vector<int>g[vNum], int cur) {
	int i, u, v, cnt = 0;
	queue<int>q;
	bfn[++cnt] = cur, vis[cur] = true;
	q.push(cur); //将初始出发点加入队列
	while (!q.empty()) { //对队列中的元素进行处理,直到队空
		u = q.front(), q.pop(); //取出队头元素
		for (i = 0; i < g[u].size(); i++) { //检查顶点u的每一个邻接点
			v = g[u][i];
			if (!vis[v]) { //顶点v为白色
				//(u,v)为树边
				bfn[++cnt] = v;
				vis[v] = true;  //加入队列前将v设置为黑色
				q.push(v); //将v加入队列
			}
 
		}
	}
}
 
//对图g进行广度优先搜索,v为顶点的数量
void bfs_traverse(vector<datatype>g[vNum], int v) {
	memset(vis, 0, sizeof(vis));//将每个顶点设置为白色
	for (int i = 1; i <= v; i++)
		if (!vis[i]) //如果顶点i为白色,则从i出发对其所在的连通分量进行bfs
			bfs(g, i);
}
 
int main() {
 
}

 And lookup:

#include<iostream>
using namespace std;
typedef int datatype;
constexpr auto N = 100;
//由并查集的两种操作可知,并查集的操作中主要涉及结点的父节点和树的根结点,
//因此可以采用树的双亲表示法表示并查集。
//由下面并查集的类型定义可知,初始并查集每个集合里就一个元素,mq即表示一个并查集。
struct mqNode {
	int pa;
	datatype data;
	mqNode() :pa(-1) {};
}mq[N];
 
//并查集的查询操作
int query(int x) {
	if (mq[x].pa == -1)return x; //x没有父节点,则x为根结点
	mq[x].pa = query(mq[x].pa); //向上查询x的父节点,并进行路径压缩,让x到根结点的路径都独立出来,成为第二层节点,链接根结点
	return mq[x].pa;
}
 
//并查集的合并操作:1.获取两个元素所在树的根结点 2.检查两个元素是否属于同一集合
void merge(int x, int y) {
	x = query(x), y = query(y);
	if (x != y)
		mq[x].pa = y;
}
 
int main() {
 
}

4. The realization principle and method of binary search based on ordered sequence, time complexity analysis.

Implementation principle:

Compare the key value of the middle element in the sequence table with the search key value, if the two are equal, the search is successful; otherwise, the middle element is used as the split point, the sequence table is divided into two sub-tables, and then the same is performed in a sub-table operate. Repeat the above process until the corresponding element is found or the sublist is empty.

Implementation principle: O(logn)

int binary_search(vector<int>sl, int k) {
	int left = 0, right = sl.size() - 1, mid;
	while (left <= right) {
		mid = (left + right) >> 1;
		if (sl[mid] == k) return mid;
		else if (sl[mid] > k) right = mid - 1;
		else left = mid + 1;
	}
	return -1;
}

2. Comprehensive questions

Including aspects such as drawing, calculation and algorithm description.

1. The structure diagram of the generalized table and the header, footer, table length and depth of the generalized table.

structure diagram

 

A generalized list is a sequence of n elements: LS = (a1, a2, ... an); where ai is an atomic item or a generalized list. n is the length of the generalized table . If ai is a generalized table, it is called a sub-table of LS.

Header and footer of generalized table: If the generalized table LS is not empty, a1 is called the head of LS, and the subtable composed of other elements is called footer.

The length of the generalized table: If the generalized table is not empty, the number of elements contained in the generalized table is called the length of the generalized table.

Depth of the generalized table: The maximum number of layers of brackets in the generalized table is called the depth of the generalized table. 

The breadth (length) of the generalized table refers to the number of data elements contained in the generalized table. example:

In the generalized table {a,{b,c,d}}, it contains one atom and one subtable, so the length of this generalized table is 2.

In the generalized table { {a,b,c}} there is only one subtable {a,b,c}, so it has length 1.

For example:
for the generalized table LS=((),a,b,(a,b,c),(a,(a,b),c)) the header
is a subtable LSH = ();
the tail is a subtable LST = (a,b,(a,b,c),(a,(a,b),c));
length of generalized table LS: 5
depth of generalized table LS: 3

2. The construction steps and construction process of the Huffman tree and the calculation method of the weighted path length.

Algorithm steps

(1) Initialization: Construct m binary trees with only one node, and obtain a binary tree set F={T1,T2...}, the weight of the leaf node (also the root node) of Ti is Wi;


(2) Selection and merging: Create a new node tmp, select two binary trees Ti and Tj with the smallest and second smallest root node weights in F, and use them as the left subtree and right subtree of tmp respectively (the order can be reversed), Construct a binary tree, the weight of node tmp is the sum of the weights of Ti and Tj


(3) Deletion and addition: delete Ti and Tj in F, and add a new binary tree with tmp as the root node to F;


(4) Repeat steps (2) and (3) until there is only one binary tree left in F. At this time, this binary tree is a Huffman tree.           
 

 

#include<iostream>
#include<queue>
using namespace std;
typedef char datatype;
constexpr auto M = 30;;
//由于结点的总数不是太大,因此可以用二叉树左右链数组的表示法做适当的扩展来表示哈夫曼树的特点
//结点定义
typedef struct hutNode {
	datatype data;
	int w, idx; //idx为结点的下标,w表示权重
	int lc, rc;
	bool operator<(const hutNode& hn)const {
		return w > hn.w; //为了使hutNode类型的优先队列中权重较小的优先级较高
	}
}huTree[M<<1];
 
//由于每一步都要选择集合F中的最小权重结点和次小权重结点,
//且F中的结点是不断更新的,因此可以使用priority_queue
//创建哈夫曼树t:参数m为叶结点的数量,data和w分别为叶结点的数据信息和叶结点的权重
void huTree_create(huTree& t, const datatype data[], int w[], int m) {
	int i;
	hutNode hn1, hn2, hn3;
	priority_queue<hutNode>f;
	for (i = 1; i <= m; i++) {
		t[i].data = data[i - 1], t[i].w = w[i - 1], t[i].idx = i;
		t[i].lc = -1, t[i].rc = -1;
		f.push(t[i]);
	}
		while (f.size() > 1) { //当f只剩下一个元素时结束循环
			hn1 = f.top(), f.pop();
			hn2 = f.top(), f.pop();
			hn3.w = hn1.w + hn2.w, hn3.idx = i;
			hn3.lc = hn1.idx, hn3.rc = hn2.idx;
 
			f.push(hn3);
			t[i++] = hn3;
		}
		t[0] = f.top(), t[0].idx = 0; //将最终哈夫曼树的根结点的编号设置为0	
}
 
int main() {
	const char* data = "EDCBA";
	int w[] = { 6,18,21,36,19 };
	huTree t;
	huTree_create(t, data, w, 5);
}

3. The general steps of the minimum spanning tree (Kruskal algorithm, Prim algorithm). There is a procedure for generating a minimum spanning tree from a graph.

Kruskal algorithm:

 

general steps

(1) Define the point set U, and define a set D, the vertex numbered v corresponds to D[v], D[v] includes two attributes: attribute d indicates the distance from v to U, and the initial value of d is INF ; The attribute to belongs to U, and the weight of the edge (v,to) is the shortest distance from v to U. Initially select any vertex v to join U, and update the value of D of v's adjacent points;

(2) Use the attribute d of D to select the vertex v with the smallest distance to U in VU and add it to U, and D[v]=INF, and the riverside (v,D[v],to) is added to the minimum generation in the tree;

(3) Utilize v to update D. When an adjacent point of v is in VU, set the weight of edge (v, u) to w. If w<D[u].d, then let D[u].d =w,D[u].to=v;

(4) Repeat steps (2) (3) until all vertices are added to U.

In short, it starts from the first vertex, and then looks for adjacent points. The information of the points is put into the small top heap (sorted by distance), and then enters the while loop, looping n-1 times; take out the top of the small top heap , that is, the minimum distance, fix it, add the vertex to u, and fix the tree edge, then traverse the connection points of the vertex, and repeat the above operation.

Prim algorithm:

Judging whether two vertices belong to the same subtree can be used and searched. 

4. The general steps of inserting and deleting a key value in a binary search tree, the process of generating a binary search tree from a key value sequence, and the process of deleting a key value in a binary search tree.

 

Guess you like

Origin blog.csdn.net/qq_62687015/article/details/129034981