2020-10-19

凸包/基数排序

好久没写博客了今天上交一篇关于数据结构作业的博客8~

求凸包,O(nlogn)

// 求凸包,不采用任何链表或者arrayList,直接采用裸数组,实质一样(其实是我不想写双向链表了...哭T_T)
#include <iostream>
#include <algorithm>
using namespace std;

int count = 0; // 凸包中点的个数
int n; // 输入元素个数

// 点对象
struct point
{
	int x, y; // 不想判断精度所以干脆不用double
};

point input[100], output[100]; // 输入的点和输出的点

// 极角排序
bool cmp(const point& a, const point& b)
{
	return (a.x < b.x) || (a.x == b.x && a.y < b.y); // 选取最左下角的元素作极点
}

int xmul(const point& a, const point& b, const point& c) // 计算叉乘
{
	return (b.x - a.x) * (c.y - b.y) - (c.x - b.x) * (b.y - a.y);
}
// 计算上下凸包(因为我们取的是左下角元素作极点)
void andrew()
{
	sort(input, input + n, cmp);
	// 上凸包
	for (int i = 0; i < n; i++) {
		while (::count > 1 && xmul(output[::count - 2], output[::count - 1], input[i]) < 0)
			::count--;
		output[::count++] = input[i];
	}
	int k = ::count;
	// 下凸包
	for (int i = n - 2; i > 0; i--) {
		while (::count > k && xmul(output[::count - 2], output[::count - 1], input[i]) < 0)
			::count--;
		output[::count++] = input[i];
	}
	if (n > 1)
		::count--;
}

int main()
{
	cout << "输入点数:";
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> input[i].x >> input[i].y;
	}
	for (int i = 0; i < n; i++) {
		cout << "Point:" << i + 1 << ": (" << input[i].x << "," << input[i].y << ")" << endl;
	}
	andrew();
	cout << "In convex:" << endl;
	for (int i = 0; i < ::count; i++) {
		cout << "Point:" << i + 1 << ": (" << output[i].x << "," << output[i].y << ")" << endl;
	}

	return 0;
}

基数排序,O(d*(radix+n)),其中d是关于radix和n的一个数

如下首先是我们类的实现

#ifndef CHAIN_H_
#define CHAIN_H
#include <iostream>
#include <sstream>
#include <iterator>
using namespace std;

template <typename T>
struct chainNode
{
	T element;
	chainNode<T>* next;

	chainNode() = default;
	chainNode(const T& theElement) :element(theElement) {}
	chainNode(const T& theElement, chainNode<T>* theNext) :element(theElement), next(theNext) {}
	operator int() const { return element; }
};

template <typename T>
class chain
{
public:
	chain(int initialcapacity = 10);
	chain(const chain<T>& theChain);
	~chain();
	int size() const { return listSize; }
	bool empty() const { return listSize == 0; }
	void insert(int theIndex, const T& theElement);
	//void erase(const T& theElement);
	void erase(int theIndex);
	T& get(int theIndex) const;
	void binSort(int range);
	void output(ostream& os) const;
	void reverse();
	void clear();
	void merge(chain<T>& first, chain<T>& second);
	class iterator;
	iterator begin() const { return iterator(firstNode); }
	iterator end() const { return iterator(nullptr); }
	class iterator
	{
	public:
		typedef forward_iterator_tag iterator_catagory;
		typedef ptrdiff_t diffrence_type;
		typedef T& reference_type;
		typedef T value_type;
		typedef T* pointer;
		iterator(chainNode<T>* it) { iter = it; }
		iterator(const iterator& it) { iter = it.iter; }
		~iterator() = default;
		T& operator*() const { return iter->element; }
		T* operator->() const { return &iter->element; }
		iterator& operator++()
		{
			iter = iter->next;
			return *this;
		}
		iterator operator++(int n)
		{
			iterator old = iter;
			iter = iter->next;
			return old;
		}
		bool operator==(const iterator it) { return iter == it.iter; }
		bool operator!=(const iterator it) { return iter != it.iter; }
	private:
		chainNode<T>* iter;
	};
private:
	chainNode<T>* firstNode;
	int listSize;
};

template <typename T>
chain<T>::chain(int initialcapacity)
{
	listSize = 0;
	firstNode = nullptr;
}

template <typename T>
chain<T>::chain(const chain<T>& theChain)
{
	listSize = theChain.listSize;
	if (listSize == 0)
	{
		firstNode = nullptr;
		return;
	}
	chainNode<T>* sourceNode = theChain.firstNode;
	firstNode = new chainNode<T>(sourceNode->element);
	sourceNode = sourceNode->next;
	chainNode<T>* targetNode = firstNode;
	while (sourceNode != nullptr)
	{
		targetNode->next = new chainNode<T>(sourceNode->element);
		targetNode = targetNode->next;
		sourceNode = sourceNode->next;
	}
	targetNode->next = nullptr;
}

template <typename T>
chain<T>::~chain()
{
	while (firstNode != nullptr)
	{
		chainNode<T>* deleteNode = firstNode;
		firstNode = firstNode->next;
		delete deleteNode;

		// equivalent notion

		/*chainNode<T>* nextNode = firstNode->next;
		delete firstNode;
		firstNode = nextNode;*/
	}
}

template <typename T>
void chain<T>::insert(int theIndex, const T& theElement)
{
	if (theIndex < 0 || theIndex > listSize)
	{
		ostringstream err;
		err << "Index out of range" << endl;
		throw err.str();
	}
	if (theIndex == 0)
		firstNode = new chainNode<T>(theElement, firstNode);
	else
	{
		chainNode<T>* currNode = firstNode;
		for (int i = 0; i < theIndex - 1; i++)
			currNode = currNode->next;
		currNode->next = new chainNode<T>(theElement, currNode->next);
	}
	listSize++;
}

//template <typename T>
//void chain<T>::erase(const T& theElement)
//{
//	// 两种写法
//	// 写法1:找到索引,O(n)
//	int index = 0;
//	chainNode<T>* currNode = firstNode;
//	for (; index < listSize; index++)
//	{
//		if (currNode->element == theElement)
//			break;
//		currNode = currNode->next;
//		index++;
//	}
//	if (index == listSize)
//		return;
//	currNode = firstNode;
//	chainNode<T>* deleteNode;
//	if (index == 0)
//	{
//		deleteNode = firstNode;
//		firstNode = firstNode->next;
//	}
//	else
//	{
//		for (int i = 0; i < index - 1; i++)
//			currNode = currNode->next;
//		deleteNode = currNode->next;
//		currNode->next = deleteNode->next;
//	}
//	delete deleteNode;
//	listSize--;
//
//	// 写法2:recursion式
//}

template <typename T>
void chain<T>::erase(int theIndex)
{
	if (theIndex < 0 || theIndex >= listSize)
		throw;
	chainNode<T>* deleteNode;
	if (theIndex == 0)
	{
		deleteNode = firstNode;
		firstNode = firstNode->next;
	}
	else
	{
		chainNode<T>* currNode = firstNode;
		for (int i = 0; i < theIndex - 1; i++)
			currNode = currNode->next;
		deleteNode = currNode->next;
		currNode->next = currNode->next->next;
	}
	delete deleteNode;
	listSize--;
}

template <typename T>
T& chain<T>::get(int theIndex) const
{
	if (theIndex < 0 || theIndex >= listSize)
	{
		ostringstream err;
		err << "Index out of range!" << endl;
		throw err.str();
	}
	chainNode<T>* currNode = firstNode;
	for (int i = 0; i < theIndex; i++)
		currNode = currNode->next;
	return currNode->element;
}

template <typename T>
void chain<T>::binSort(int range)
{
	chainNode<T>** bottom, ** top;
	bottom = new chainNode<T> * [range + 1];
	top = new chainNode<T> * [range + 1];
	for (int b = 0; b <= range; b++)
		bottom[b] = nullptr;
	for (;firstNode != nullptr;firstNode = firstNode->next)
	{
		int theBin = firstNode->element;
		if (bottom[theBin] == nullptr)
			bottom[theBin] = top[theBin] = firstNode;
		else
		{
			top[theBin]->next = firstNode;
			top[theBin] = firstNode;
		}
	}
	chainNode<T>* y = nullptr;
	for (int theBin = 0; theBin <= range; theBin++)
	{
		if (bottom[theBin] != nullptr)
		{
			if (y == nullptr)
				firstNode = bottom[theBin];
			else
				y->next = bottom[theBin];
			y = top[theBin];
		}
	}
	if (y != nullptr)
		y->next = nullptr;
	delete[]bottom;
	delete[]top;
}

template <typename T>
void chain<T>::output(ostream& os) const
{
	chainNode<T>* currNode = firstNode;
	while (currNode != nullptr)
	{
		os << currNode->element << "  ";
		currNode = currNode->next;
	}
}

template <typename T>
void chain<T>::reverse()
{
	// 方法也有两种,其中一种是recursion
	// 方法1:原地逆转,O(n)
	if (firstNode == nullptr || firstNode->next == nullptr)
		return;
	chainNode<T>* last = nullptr, * curr = firstNode, * next = nullptr;
	while (curr != nullptr)
	{
		next = curr->next;
		curr->next = last;
		last = curr;
		curr = next;
	}
	firstNode = last;

	// 方法2不表
}

template <typename T>
void chain<T>::clear()
{
	while (firstNode != nullptr)
	{
		chainNode<T>* nextNode = firstNode->next;
		delete firstNode;
		firstNode = nextNode;
	}
	listSize = 0;
	firstNode = nullptr;
}

template <typename T>
void chain<T>::merge(chain<T>& first, chain<T>& second)
{
	chain<T>::iterator iter1 = first.begin();
	chain<T>::iterator iter2 = second.begin();
	while (iter1 != nullptr && iter2 != nullptr)
	{
		if (*iter1 <= *iter2) this->insert(listSize, *iter1++);
		else this->insert(listSize, *iter2++);
	}
	while (iter1 != nullptr) this->insert(listSize, *iter1++);
	while (iter2 != nullptr) this->insert(listSize, *iter2++);
	first.clear();
	second.clear();
}
#endif

根据上述类写出基数排序的代码

#include "链表和结构定义.h"
// 基数排序的实现,基本思想基于箱子排序
//
//struct studentRecord
//{
//	int score;
//	studentRecord() = default;
//	studentRecord(int score) :score(score) {}
//	studentRecord(const studentRecord& stuRec) :score(stuRec.score) {}
//	~studentRecord() = default;
//	operator int() { return score; }
//};

// 类外方法,时间复杂度O(d*(radix+n)),d是n对radix的位数
void radixSort(chain<int>& theChain, int radix)
{
	int d = 0; // 确定基数排序的最大位数
	int len = theChain.size(); // 直接取chain的长度防止反复调用函数带来的开销
	for (int i = 0; i < len; i++) { // O(listSize^2)
		int temp = theChain.get(i);
		int count = 0;
		do {
			temp /= radix;
			count++;
		} while (temp);
		if (d < count)
			d = count;
	}
	chain<int>* theBin = new chain<int>[radix+1]; // radixSort关键思想,箱子排序
	int base = 1;
	for (int i = 1; i <= d; i++) { // d次箱子排序
		for (int j = 0; j < len; j++) { // 节点分配 O(listSize)
			int bin = theChain.get(0);
			theChain.erase(0);
			theBin[bin / base % radix].insert(0, bin);
		}
		for (int b = radix; b >= 0; b--) { // 收获节点O(radix)
			while (!theBin[b].empty()) {
				int bin = theBin[b].get(0);
				theBin[b].erase(0);
				theChain.insert(0, bin);
			}
		}
		base *= radix; // 下一次需要从高位算起
	}
	delete[]theBin;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值