数据结构课程——第一次作业

T1:Gram_ham实现凸包算法:

(1)思路:

 数据结构课程——第一次作业_第1张图片数据结构课程——第一次作业_第2张图片

(2)代码:

#include
#include
#include
#include
#include

using namespace std;
//备注:这里把 顶点 用 一棵树tree 来形象化的表示,没啥别的意思。。。

//函数声明:
vector> outerTrees(vector> &trees); // 返回 一个二维数组,就是最终的凸包节点次序
int cross(const vector & p, const vector & q, const vector & r);//计算 极角
int distance(const vector & p, const vector & q); //计算2点之间的距离平方



int main()
{
	//只需要求一个 凸包
	//处理输入:
	int T;
	cout << "请输入需要测试的 次数: " << endl;
	cin >> T; //测试次数
	while (T--)
	{
		cout << "请输入节点个数 :" << endl;
		int n; // 有n个 顶点
		cin >> n;
		vector> trees(n, vector(2, 0));
		for (int i = 0; i < n; i++)
		{
			cout << "请输入第" << i+1 << "个坐标: ";
			cin >> trees[i][0] >> trees[i][1];  //得到坐标点(x,y)
		}

		//(1)计算凸包的 调用 outerTreees函数,得到一个二维数组,其中存储了 凸包的节点次序的二维数组
		vector> vec = outerTrees(trees);
		//(2)输出凸包的顶点次序:
		int size = vec.size();
		cout << "这个凸包的 顶点坐标 次序如下: " << endl;
		for (int i = 0; i <= size - 1; i++)
		{
			cout << "(" << vec[i][0] << "," << vec[i][1] << ")" << " ";
		}
		cout << endl;
	}
	return 0;
}

vector> outerTrees(vector> &trees) {
	int n = trees.size();
	if (n < 4) {
		return trees;
	}
	int bottom = 0;
	//找到 y 最小的点 bottom
	for (int i = 0; i < n; i++) {
		if (trees[i][1] < trees[bottom][1]) {
			bottom = i;
		}
	}
	swap(trees[bottom], trees[0]);
	//以 bottom 原点,按照极坐标的角度大小进行排序 
	sort(trees.begin() + 1, trees.end(), [&](const vector & a, const vector & b) {
		int diff = cross(trees[0], a, b);
		if (diff == 0) {
			return distance(trees[0], a) < distance(trees[0], b);
		}
		else {
			return diff > 0;
		}
	});
	//对于凸包最后且在同一条直线的元素按照距离从大到小进行排序 
	int r = n - 1;
	while (r >= 0 && cross(trees[0], trees[n - 1], trees[r]) == 0) {
		r--;
	}
	for (int l = r + 1, h = n - 1; l < h; l++, h--) {
		swap(trees[l], trees[h]);
	}
	stack st;
	st.emplace(0);
	st.emplace(1);
	for (int i = 2; i < n; i++) {
		int top = st.top();
		st.pop();
		//如果当前元素与栈顶的两个元素构成的向量顺时针旋转,则弹出栈顶元素 
		while (!st.empty() && cross(trees[st.top()], trees[top], trees[i]) < 0) {
			top = st.top();
			st.pop();
		}
		st.emplace(top);
		st.emplace(i);
	}

	vector> res;
	while (!st.empty()) {
		res.emplace_back(trees[st.top()]);
		st.pop();
	}
	return res;
}

int cross(const vector & p, const vector & q, const vector & r) {
	return (q[0] - p[0]) * (r[1] - q[1]) - (q[1] - p[1]) * (r[0] - q[0]);
}

int distance(const vector & p, const vector & q) {
	return (p[0] - q[0]) * (p[0] - q[0]) + (p[1] - q[1]) * (p[1] - q[1]);
}

T2:利用递归 —— 实现 输出杨辉三角的 第i行的 所有 元素:

(1)思路:

<1>递归之处:第i行的第j个元素 = 第i-1行的第j-1个元素 + 第i-1行的第j个元素

<2>所有的递归,都会有出口,比如这里:第1行 或者 第i行的第1列 或者 第i行的最后一列 这些元素的值就是 "1",不能再相深层递归了

(2)代码:

#include
using namespace std;
//利用 递归 实现输出 杨辉三角的 第i行数据

int data_i_j(int i, int j) //作用:递归 返回 第i行 ,第j列的 元素
{
	//(0)出口:
	if (i == 1 || j == 1 || j == i) //第1行 或者 第i行的第1列 或者 第i行的最后一列
	{
		return 1;
	}
	//(1)向上面一层递归:
	return data_i_j(i - 1, j - 1) + data_i_j(i - 1, j);
}

int main()
{
	int T;
	cout << "请输入需要测试的 次数 :" << endl;
	cin >> T;
	while (T--)
	{
		cout << "请输入 第几行 : " << endl;
		int i;
		cin >> i;
		//输出 第i行的 所有 杨辉三角 元素:
		for (int j = 1; j <= i; j++)
		{
			cout << data_i_j(i, j) << " ";
		}
		cout << endl;
	}

	return 0;
}

T3:利用双向链表存储 学生的信息:

(1)思路:

<1>结构体NODE: 数据 + pre指针 + next指针

      结构体LIST:       Head指针 + Tail指针 + size节点个数(不包含head 和 tail)

<2>可以在 结构体外面写 一个函数给 LIST进行初始化, 也可以 就在里面写一个 构造函数,效果是一样的,这是必须的,因为:

第一:初始的2个指针如果不开辟空间,就是NULL指针,用了就报错

第二:双向链表初始结构就是 head 和 tail的相互指向,需要初始设置这一步

<3>至于 添加 和 删除 节点: 无非就是 修改指针域 罢了

(2)代码:

#include
#include
using namespace std;

//实现双端环形链表 结构
//环形结构比较 容易实现 , 只要保证 第一个节点 最后一个节点相互指向就可以了

int MaxNum = 1000; //最大容量

//节点数据结构
typedef struct node
{
	int Id;   //学号
	string name; //姓名
	struct node* Pre;//上一节点
	struct node* Next;//下一节点
}NODE, *PNODE;

//双向链表数结构
typedef struct List
{
	NODE* pHead;//链表头指针
	NODE* pTail;//链表尾指针
	int size; //当前节点的 数量
	//默认构造函数:
	List()
	{
		this->size = 0;
		//防止使用空指针:在堆上创建2个指针给head和tail比较好
		pHead = new NODE;
		pTail = new NODE;
		//初始的循环双向链表结构
		pHead->Next = pTail;
		pHead->Pre = pTail; //这个不动
		pTail->Pre = pHead;
		pTail->Next = pHead; //这个不动
	}
}LIST;

//定义2个函数:
int newStudent(List &L, int stu_id, string stu_name)
{
	//(0)检查是否达到人数的上限:
	if (L.size == MaxNum)
	{
		return L.size; //不能添加了。。。
	}
	//(1)创建一个 新的node*节点,具有id数据,并且 加入到L队列的末尾
	NODE* new_node = new NODE;
	new_node->Id = stu_id;
	new_node->name = stu_name;
	//--以下更新4个指针域:
	new_node->Next = L.pTail;
	new_node->Pre = L.pTail->Pre;
	L.pTail->Pre->Next = new_node;//成功insert一个节点
	//更新 pTail的pre指针
	L.pTail->Pre = new_node; //这4步的指针修改次序不能乱!!!
	//更新size 并且返回
	L.size++;
	return L.size;
}
int delStudent(List& L, int stu_id)
{
	//从前向后遍历 —— 找到具有 这个 id的 节点,然后 删除节点
	//如果没有找到,就不用任何操作:
	NODE* tmp = L.pHead->Next;
	while (tmp != L.pTail)
	{
		if (tmp->Id == stu_id)
		{
			//删除当前节点,只要修改 前一个节点的next 和 后一个节点的pre就行
			tmp->Pre->Next = tmp->Next;
			tmp->Next->Pre = tmp->Pre;
			//--
			L.size--;
			delete tmp;
			break;
		}
		//--
		tmp = tmp->Next;
	}
	return L.size;
}

int main()
{
	List stuList;
	int cnt = 0;
	//(1)循环测试 : 添加1-10号学生
	for (int i = 1; i <= 10; i++)
	{
		char ch = 'a' + i;
		string str = "Xi_model_";
		str = str + ch;
		cnt = newStudent(stuList, i , str);
	}
	cout << "当前学生人数 :" << cnt << endl;
	//(2)删除2,3号学生
	cnt = delStudent(stuList, 2);
	cnt = delStudent(stuList, 3);
	cout << "当前学生人数 :" << cnt << endl;
	//(3)遍历stuList
	NODE* tmp = stuList.pHead->Next;
	while (tmp != stuList.pTail)
	{
		cout << tmp->Id << " " << tmp->name << endl;;
		tmp = tmp->Next;
	}
	cout << endl;
	return 0;
}

你可能感兴趣的:(数据结构和算法相关,数据结构,算法,c++)