《数据结构、算法与应用 —— C++语言描述》学习笔记 — 线性表 —— 链式描述 —— 应用

本文是关于《数据结构、算法与应用 —— C++语言描述》的学习笔记,重点讨论线性表的链式描述在箱子排序和凸包问题中的应用。文章详细介绍了箱子排序的链表实现,包括学生记录结构、实现和模板方法,以及基数排序的原理和实现。此外,还探讨了凸包问题的算法和实现,包括判断共线、找到极点、计算凸包的详细步骤,以及相关代码测试和复杂度分析。
摘要由CSDN通过智能技术生成

一、箱子排序

考虑用一个链表保存一个班级学生的清单。我们简化节点的数据为:学生姓名和学生成绩。考虑到成绩范围是有限值,如果我们采用冒泡排序等方式,其时间复杂度都为O( n 2 n^{2} n2) 。这里我们使用桶排序可以得到对大量数据的更快速排序。桶排序的基本思想是选举与数据范围一致的个数的桶,然后将数据分别放在桶中,最后从桶中将数据重新放回容器中。
使用链表实现的桶排序,其过程如下:
1、逐步删除输入链表的节点,把删除的节点分配到相应的箱子里。
2、把每一个箱子中的链表收集并链接起来。

1、学生记录结构

struct StudentRecord
{
   
	int m_iScore;
	std::string *m_pName;

	bool operator!=(const StudentRecord& other)
	{
   
		return (*m_pName != *other.m_pName);
	}
};

ostream& operator<<(ostream& os, const StudentRecord& record)
{
   
	os << *record.m_pName << " " << record.m_iScore << endl;
	return os;
}

2、实现

void binSort(chain<StudentRecord>& records, int range)
{
   
	vector<chain<StudentRecord>> bins(range + 1);

	while (!records.empty())
	{
   
		auto record = records.get(0);
		records.erase(0);
		bins[record.m_iScore].insert(0, record);
	}

	for (auto iter = bins.rbegin(); iter != bins.rend(); iter++)
	{
   
		auto bin = *iter;
		while (!bin.empty())
		{
   
			auto record = bin.get(0);
			bin.erase(0);
			records.insert(0, record);
		}
	}
}

在第一个while循环中,我们每次都从原链表获取并删除头结点,在桶中头结点前插入,因此时间复杂度为O(n);在第二个for循环中,操作相似,但是循环执行的次数需要包含桶的个数,因此时间复杂度为O(n+range)。因此上述排序方式总的时间复杂度为O(n+range)。

3、作为链表模板类方法实现

仔细观察上述代码,不难发现,我们其实并不需要真正的将链表节点删除。它们实际上是从原始链表中移动到桶中,再回到原链表中。因此,如果我们将桶排序作为模板方法,可以直接把各桶收尾节点相连而不需移动节点,也不必再newdelete节点,那么其效率将会有很大提升。其思路如图:
在这里插入图片描述

template<class T>
inline void chain<T>::binSort(int range)
{
   
	chainNode<T>** bottom, ** top;
	bottom = new chainNode<T>*[range + 1];
	top = new chainNode<T>*[range + 1];
	for (int i = 0; i < range + 1; ++i)
	{
   
		bottom[i] = nullptr;
	}

	for (; first != nullptr; first = first->next)
	{
   
		int binIndex = first->element;
		if (bottom[binIndex] == nullptr)
		{
   
			bottom[binIndex] = top[binIndex] = first;
		}
		else
		{
   
			top[binIndex]->next = first;
			top[binIndex] = top[binIndex]->next;
		}
	}

	chainNode<T>* lastTop = nullptr;
	for (int i = 0; i <= range; ++i)
	{
   		
		if (bottom[i] != nullptr)
		{
   
			if (first == nullptr)
			{
   
				first = bottom[i];				
			}
			else
			{
   
				lastTop->next = bottom[i];
			}
			lastTop = top[i];
		}
	
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值