二分法查找有序表的通用算法(可查链表,数组,字符串...等等)

news2024/11/20 9:14:36

find_binary函数 

注意事项:

(1)你设计的迭代器模板中必须有using value_type = T,且有加减运算功能,其本上能与C++标准库std中一样。

(2)集合必须是有序的。

下面是函数代码:

/// <summary>
/// 二分法查找有序表的通用算法(可查链表,数组,字符串...等等)
/// 例子:
///  vector<int> v;
///  find_binary(b.begin(),v.end(),3);  // Inde返回 (-1, *Iterator == ?)
/// 
///  vector<int> v = {3};
///  find_binary(b.begin(),v.end(),3);  // 返回  (Index == 0, *Iterator == 3)
///  
///  const char* sz = "abcdefgb";
///  auto f3 = lf::find_binary(sz, sz + 8, 'c');  //返回  (Index == 2, *Iterator == c)
/// </summary>
/// <typeparam name="IteratorType">迭代器类型</typeparam>
/// <typeparam name="value_type">值类型</typeparam>
/// <param name="itBegin">开始位置</param>
/// <param name="itEnd">结束位置</param>
/// <param name="vtFindValue">查找值</param>
/// <returns>返回索引与指向vtFindValue的迭代器</returns>
/// 创建时间: 2024-07-03     最后一修改时间:2024-07-03  (基本上已经测试)
template<typename IteratorType,typename value_type = IteratorType::value_type>
FindResult<IteratorType> find_binary(const IteratorType& itBegin, 
	const IteratorType& itEnd, const value_type& vtFindValue)
{

	FindResult<IteratorType> fr;  

	auto beg = itBegin;
	auto end = itEnd;
	int nCount = end - beg;

	if (nCount == 0) return fr;


	if (*(itEnd-1) > *itBegin) {//从小到大排列

		auto mid = beg + nCount / 2;

		while (mid != itEnd){

			if(*mid == vtFindValue){
				fr.Iter = mid;
				fr.Index = mid - itBegin;

				return fr;
			}

			if (vtFindValue < *mid)
				end = mid;
			else
				beg = mid + 1;  //在mid之后查找

			mid = beg + (end - beg) / 2;   //新的中间点
		}	 

	}else{ //从大到小排列 
 
		auto mid = beg + nCount / 2;

		while (mid != itEnd) {

			if (*mid == vtFindValue) {
				fr.Iter = mid;
				fr.Index = mid - itBegin;

				return fr;
			}

			if (vtFindValue > *mid)
				end = mid;
			else
				beg = mid + 1;  //在mid之后查找

			mid = beg + (end - beg) / 2;   //新的中间点
		}
	}

	return fr;
}

例子代码:

 
int main()
{
 
	std::vector<int> v1 = { 1,2,3,4,5,6 ,7,8,9,10 };
	_DList<int> d1 = { 1,2,3,4,5,6 ,7,8,9,10 };
	const char* sz = "abcdefgb";

	auto f1 = lf::find_binary(v1.begin(), v1.end(), 3);

	cout << *(f1.Iter) << "\n";
	cout << f1.Index << "\n";
	cout << "----------" << "\n";

	auto f2 = lf::find_binary(d1.begin(), d1.end(), 3);

	cout << *(f2.Iter) << "\n";
	cout << f2.Index << "\n";
	cout << "----------" << "\n";

	auto f3 = lf::find_binary(sz, sz + 8, 'c');

	cout << *(f3.Iter) << "\n";
	cout << f3.Index << "\n";

	cout << "----------" << "\n";

	std::vector<int> v2 = { 10,9,8,7,6,5,4,3,2,1 };

	auto f4 = lf::find_binary(v2.begin(), v2.end(), 3);

	cout << *(f4.Iter) << "\n";
	cout << f4.Index << "\n";

	cout << "----------" << "\n";
 
}

输出:

完整代码如下:

/*******************************************************************************************
文件名						: _AlgorithmLibrary.h

功能							: 算法库

作者							: 李锋

手机							: 13828778863

Email						: ruizhilf@139.com

创建时间						: 2024年07月02日

最后一次修改时间				:  2024年07月02日
*********************************************************************************************/
#pragma once


//Algorithm library  算法库

#include "_Macro.h"

 
/*****************************************************************************
	
								排序


 ****************************************************************************/

//排序
//参考:https://blog.csdn.net/qq_45615577/article/details/115257685

//排序的概念
/*
排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。
稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次 序保持不变,即在原序列中,r[i] = r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排 序算法是稳定的;否则称为不稳定的。
内部排序:数据元素全部放在内存中的排序。
外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序。
————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY - SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https ://blog.csdn.net/qq_45615577/article/details/115257685
*/
_LF_BEGIN_

/// <summary>
/// 选择排序---直接选择排序
/// 每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,
/// 直到全部待排序的 数据元素排完 。
/// 找出序列中的最小关键字,然后将这个元素与序列首端元素交换位置。例如,序列前i个
/// 元素已经有序,从第i + 1到第n个元素中选择关键字最小的元素,假设第j个元素为最小
/// 元素,则交换第j个元素与第i + 1个元素的位置。依次执行此操作,直到第n - 1个元素
/// 也被确定。
/// </summary>
/// <typeparam name="T">类型</typeparam>
/// <param name="pData">开始位置</param>
/// <param name="nCount">元素个数</param>
/// <param name="so">排序顺序,默认从小到大</param>
/// 创建时间: 2024-07-01     最后一修改时间:2024-07-01
/// 参考网址:https://blog.csdn.net/qq_45615577/article/details/115257685 
template<class T>
void sort_selection(T* pData, const size_t& nCount, const bool& bMinMax = true)
{

	/*
		7 4 5 9 8 2 1
		1 4 5 9 8 2 7
		  2 5 9 8 4 7
			4 9 8 5 7
			  5 8 9 7
				7 9 8
				  8 9


		在 [0 , n-1] 中找出最小的放在第一位
		在 [1 , n-1] 中找出最小的放在第二位
		...


	*/

	if (pData == null || nCount == 0) return;

	int nSortedCount = 0;  //已排序好的个数

	if (bMinMax) {

		while (nSortedCount < nCount) {

			int  minIndex = nSortedCount;

			//在[nStart, nCount-1] 中找出最小值
			for (int n = nSortedCount + 1; n < nCount; ++n) {

				if (*(pData + n) < *(pData + minIndex)) {

					minIndex = n;
				}
			}

			if (minIndex != nSortedCount) {

				T tmp = *(pData + minIndex);
				*(pData + minIndex) = *(pData + nSortedCount);
				*(pData + nSortedCount) = tmp;
			}

			++nSortedCount;
		}

	}
	else {

		while (nSortedCount < nCount) {

			int  maxIndex = nSortedCount;

			//在[nStart, nCount-1] 中找出最大值
			for (int n = nSortedCount + 1; n < nCount; ++n) {

				if (*(pData + n) > *(pData + maxIndex)) {
					maxIndex = n;
				}
			}

			if (maxIndex != nSortedCount) {

				T tmp = *(pData + maxIndex);
				*(pData + maxIndex) = *(pData + nSortedCount);
				*(pData + nSortedCount) = tmp;
			}
			++nSortedCount;
		}
	}

}


/// <summary>
/// 返回最小值的位置
///		lf::_DList<int> d1 = { 1,3,5,8,2,0 };
///		lf::_DList<int> d2 = { 1 };
///		lf::_DList<int> d3 = { };
///		vector<int> v = { 1,3,5,8,2,0 };
///
///		_pin(*lf::Min(d1.begin(), d1.end()));  //输出: 0
///		_pin(*lf::Min(d2.begin(), d2.end()));  //输出: 1
///		_pin(*lf::Min(d3.begin(), d3.end()));  //报错,最少一个元素
///
///		_pin(*lf::Min(v.begin(), v.end()));  //输出: 0
/// 
/// 	_string s = _t("sdwsffa");
///		_pin(*lf::Min(s.begin(), s.end()));  //输出: a

/// </summary>
/// <typeparam name="IteratorClass"></typeparam>
/// <param name="itBegin"></param>
/// <param name="itEnd"></param>
/// <returns></returns>
/// 创建时间: 2024-07-02     最后一修改时间:2024-07-02
template<typename IteratorClass>
IteratorClass Min(IteratorClass itBegin, IteratorClass itEnd) {

	assert(itBegin != itEnd);

	IteratorClass result = itBegin;

	while (itBegin != itEnd) {

		if (*result > *itBegin)
			result = itBegin;
		++itBegin;
	}

	return result;
}


/// <summary>
/// 
/// </summary>
/// <typeparam name="IteratorClass"></typeparam>
/// <param name="itBegin"></param>
/// <param name="itEnd"></param>
/// <returns></returns>
/// 创建时间: 2024-07-02     最后一修改时间:2024-07-02
template<typename IteratorClass>
IteratorClass Max(IteratorClass itBegin, IteratorClass itEnd) {

	assert(itBegin != itEnd);

	IteratorClass result = itBegin;

	while (itBegin != itEnd) {
		if (*result < *itBegin)
			result = itBegin;

		++itBegin;
	}
	return result;
}



/// <summary>
/// 
/// </summary>
/// <typeparam name="IteratorClass"></typeparam>
/// <param name="it1"></param>
/// <param name="it2"></param>
/// 创建时间: 2024-07-02     最后一修改时间:2024-07-02
template<typename IteratorClass>
void Swap(IteratorClass it1, IteratorClass it2) {

	//std::cout << "===================================\n";
	//_pin(*it1);
	//_pin(*it2);

	auto tmp = *it1;  //如果*it2是 int& 则,tmp 的类型是int, 并不是int&。

	*it1 = *it2;
	*it2 = tmp;

	//_pin(*it1);
	//_pin(*it2);
	//std::cout << "===================================\n";
}


/// <summary>
/// 	lf::_DList<int> d4 = {1,2,3,6,5,4};
///		lf::sort_selection(d4.begin(), d4.end(), _SortOrder::s_Minmax);
///		_pcn(d4);  //输出:d4={1,2,3,4,5,6}
///		lf::sort_selection(d4.begin(), d4.end(), _SortOrder::s_Maxmin);
///		_pcn(d4); //输出:d4={6,5,4,3,2,1}
/// 
///		_string s2 = _t("_DListNodeIterator,abcd,efg");
///		_pcn(s2); //s2=_DListNodeIterator,abcd,efg
///		lf::sort_selection(s2.begin(), s2.end(), _SortOrder::s_Minmax);
///		_pcn(s2); //s2=,,DILN_aabcddeeefgioorrsttt
///		lf::sort_selection(s2.begin(), s2.end(), _SortOrder::s_Maxmin);
///		_pcn(s2); //s2=tttsrrooigfeeeddcbaa_NLID,,
/// </summary>
/// <typeparam name="IteratorClass"></typeparam>
/// <param name="itBegin"></param>
/// <param name="itEnd"></param>
/// <param name="so"></param>
/// 创建时间: 2024-07-01     最后一修改时间:2024-07-02(已测试)
template<typename IteratorClass>
void sort_selection(IteratorClass itBegin, IteratorClass itEnd, const bool& bMinMax = true)
{

	/*
		7 4 5 9 8 2 1
		1 4 5 9 8 2 7
		  2 5 9 8 4 7
			4 9 8 5 7
			  5 8 9 7
				7 9 8
				  8 9

		7 2 2 2 2 2 2
		2 7 2 2 2 2 2
		  2 7 2 2 2 2
			2 7 2 2 2
			  2 7 2 2
				2 7 2
				  2 7

		在 [0 , n-1] 中找出最小的放在第一位
		在 [1 , n-1] 中找出最小的放在第二位
		...


	*/

	if (bMinMax) {

		while (itBegin != itEnd) {
			//在[itBegin + 1, itEnd] 中找出最小值,与itBegin交换		 
			Swap(itBegin, Min(itBegin, itEnd));
			++itBegin;
		}
	}
	else {
		while (itBegin != itEnd) {
			//在[itBegin + 1, itEnd] 中找出最小值,与itBegin交换
			Swap(itBegin, Max(itBegin, itEnd));
			++itBegin;
		}
	}
}




/*****************************************************************************

								查找

顺序查找

二分查找

插值查找、

斐波那契查找

分块查找


哈希查找


树表查找
 ****************************************************************************/
template<typename IteratorType>
struct FindResult
{
	/// <summary>
	/// 如果没找到 Index == -1
	/// </summary>
	int Index;
	IteratorType Iter;

public:

	inline FindResult()
	{
		Index = -1;
	}

	inline FindResult(const FindResult& r)
	{
		Index = r.Index;
		Iter = r.Iter;
	}
};


/// <summary>
/// 顺序查找
/// 
/// 注意:
///		如果是向后查找,则返回的索引是以itFirst开始算来,第一个为 0,即itFirst为0。
///		如果是向前揸找,则返回的索引是以itLast开始算起,第一个,即itLast为0。
///		 
/// </summary>
/// <typeparam name="IteratorType"></typeparam>
/// <typeparam name="DataType"></typeparam>
/// <param name="itBegin"></param>
/// <param name="itEnd"></param>
/// <param name="tValue"></param>
/// <param name="bBackward"></param>
/// <returns></returns>
/// 创建时间: 2024-07-03     最后一修改时间:2024-07-03
template<typename IteratorType, typename DataType>
FindResult<IteratorType> find_sequential(IteratorType itFirst, IteratorType itLast,
	const DataType& tFindValue, const bool& bBackward = true)
{

	FindResult<IteratorType> fr;
	fr.Index = -1;

	int n = 0;

	
	if (bBackward) {  //向后
		while (true)
		{
			if (*itFirst == tFindValue) {
				fr.Index = n;
				fr.Iter = itFirst;
				break;
			}
			++n;
			++itFirst;
			if (itFirst == itLast) break;
		}
	}
	else {

		while (true)
		{
			if (*itLast == tFindValue) {
				fr.Index = n;
				fr.Iter = itLast;
				break;
			}
			++n;
			--itLast;
			if (itFirst == itLast) break;
		}

	}


	return fr;
}



/// <summary>
/// 集合类必须带有 begin() 和 end() 函数
/// 例子:
///		std::vector<int> v = { 1,2,3,23,435,4646,34 };
///		lf::_DList<int> d = { 1,2,3,23,435,4646,34 };
///		if (lf::IsExists(d, 23))
///		{
///		cout << "存在23.\n";
///		}
///		if (lf::IsExists(v, 55))
///		{
///			cout << "存在55.\n";
///		}
/// </summary>
/// <typeparam name="value_type"></typeparam>
/// <typeparam name="CollectionClass"></typeparam>
/// <param name="col"></param>
/// <param name="value"></param>
/// <returns></returns>
/// 创建时间: 2024-07-03     最后一修改时间:2024-07-03
template<typename CollectionClass, typename value_type = CollectionClass::value_type>
bool IsExists(const CollectionClass& col, const value_type& value)
{
	auto itbegin = col.begin();
	auto itend = col.end();

	while (itbegin != itend)
	{
		if (*itbegin == value)
			return true;

		++itbegin;
	}

	return false;
}


 
/// <summary>
/// 二分法查找有序表的通用算法(可查链表,数组,字符串...等等)
/// 例子:
///  vector<int> v;
///  find_binary(b.begin(),v.end(),3);  // Inde返回 (-1, *Iterator == ?)
/// 
///  vector<int> v = {3};
///  find_binary(b.begin(),v.end(),3);  // 返回  (Index == 0, *Iterator == 3)
///  
///  const char* sz = "abcdefgb";
///  auto f3 = lf::find_binary(sz, sz + 8, 'c');  //返回  (Index == 2, *Iterator == c)
/// </summary>
/// <typeparam name="IteratorType">迭代器类型</typeparam>
/// <typeparam name="value_type">值类型</typeparam>
/// <param name="itBegin">开始位置</param>
/// <param name="itEnd">结束位置</param>
/// <param name="vtFindValue">查找值</param>
/// <returns>返回索引与指向vtFindValue的迭代器</returns>
/// 创建时间: 2024-07-03     最后一修改时间:2024-07-04  (初步测试)
template<typename IteratorType,typename value_type = IteratorType::value_type>
FindResult<IteratorType> find_binary(const IteratorType& itBegin, 
	const IteratorType& itEnd, const value_type& vtFindValue)
{

	FindResult<IteratorType> fr;  

	auto beg = itBegin;
	auto end = itEnd;
	int nCount = end - beg;

	if (nCount == 0) return fr;


	if (*(itEnd-1) > *itBegin) {//从小到大排列

		auto mid = beg + nCount / 2;

		while (mid != itEnd){

			if(*mid == vtFindValue){
				fr.Iter = mid;
				fr.Index = mid - itBegin;

				return fr;
			}

			if (vtFindValue < *mid)
				end = mid;
			else
				beg = mid + 1;  //在mid之后查找

			mid = beg + (end - beg) / 2;   //新的中间点
		}	 

	}else{ //从大到小排列 
 
		auto mid = beg + nCount / 2;

		while (mid != itEnd) {

			if (*mid == vtFindValue) {
				fr.Iter = mid;
				fr.Index = mid - itBegin;

				return fr;
			}

			if (vtFindValue > *mid)
				end = mid;
			else
				beg = mid + 1;  //在mid之后查找

			mid = beg + (end - beg) / 2;   //新的中间点
		}
	}

	return fr;
}






_LF_END_

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1896099.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

flask的进阶使用方法

【 一 】一对多关系 # 1 一对一 [本质就是一对多--》多的那个唯一] # 2 一对多 # 3 多对多1.1 关系 #### 一对多关系 class Hobby(Base):__tablename__ hobbyid Column(Integer, primary_keyTrue)caption Column(String(50), default篮球)def __str__(self):return sel…

C++ | Leetcode C++题解之第213题打家劫舍II

题目&#xff1a; 题解&#xff1a; class Solution { public:int robRange(vector<int>& nums, int start, int end) {int first nums[start], second max(nums[start], nums[start 1]);for (int i start 2; i < end; i) {int temp second;second max(fi…

django学习入门系列之第四点《案例 博客案例》

文章目录 container面板案例 博客案例往期回顾 container 堆叠到两边 <div class"container-fluid clearfix"><div class"col-sm-9">1</div><div class"col-sm-3">2</div> </div>放在中间 <div clas…

嵌入式Linux系统编程 — 6.7 实时信号

目录 1 什么是实时信号 2 sigqueue函数 3 sigpending()函数 1 什么是实时信号 等待信号集只是一个掩码&#xff0c;它并不追踪信号的发生次数。这意味着&#xff0c;如果相同的信号在被阻塞的状态下多次产生&#xff0c;它只会在信号集中被记录一次&#xff0c;并且在信号集…

【Python实战因果推断】20_线性回归的不合理效果10

目录 Neutral Controls Noise Inducing Control Feature Selection: A Bias-Variance Trade-Off Neutral Controls 现在&#xff0c;您可能已经对回归如何调整混杂变量有了一定的了解。如果您想知道干预 T 对 Y 的影响&#xff0c;同时调整混杂变量 X&#xff0c;您所要做的…

项目基础知识

1.JDBC编程和MySQL数据库 数据库的连接&#xff08;以前写qq项目时的代码&#xff09; package com.wu.Util; import java.sql.*; public class JDBCUtil {private static JDBCUtil jdbcUtil null;private JDBCUtil() {}public static JDBCUtil getJdbcUtil() {if (jdbcUtil…

RUP开发模型-系统架构师(二十三)

1、RUP是一个二维软件开发模型&#xff0c;其核心特点之一是&#xff08;&#xff09;。RUP将软件开发周期划分多个循环&#xff0c;每个循环由4个连续阶段组成&#xff0c;每个阶段完成确定的任务。设计及确定系统的体系结构&#xff0c;制定工作计划及资源要求在&#xff08;…

Edge浏览器油猴插件的安装与使用

油猴 (又称篡改猴或Tampermonkey) 是最流行的浏览器扩展之一。它允许用户自定义并增强网页的功能。用户脚本是小型 JavaScript 程序&#xff0c;可用于向网页添加新功能或修改现有功能。使用油猴&#xff0c;您可以轻松在任何网站上创建、管理和运行这些用户脚本。 1.插件的安…

标量场与向量场

标量场与向量场 flyfish 场 是一个函数&#xff0c;它把空间中的每一点关联到一个数值或一个数学对象&#xff08;如向量、张量等&#xff09;。在物理学中&#xff0c;场可以描述许多物理现象&#xff0c;例如温度分布、电场、磁场、压力场等。 标量场 标量场 是一个函数&…

2024 年最佳 Figma 字体

字体不仅仅是文本字符&#xff0c;它们还塑造了用户体验。从引导用户浏览界面到传达品牌个性&#xff0c;字体对于设计​​至关重要。然而&#xff0c;找到适合您的网站或应用风格的完美字体可能具有挑战性。 但不要害怕&#xff0c;我们会帮助您&#xff01;请继续关注&#x…

c语言----队列

很久没有写文章了。因为放假了嘛&#xff0c;给自己稍微放松了一下&#xff0c;所以最近的更新很慢。呜呜下一次一定改。然后咧。今天我想与大家分享的是队列。虽然这个知识点我们应该在讲了堆的实现就应该写的&#xff0c;但是后面忘了&#xff0c;以为自己是写了的。但是昨天…

SQL二次注入原理分析

二次注入在测试的时候比较少见&#xff0c;或者说很难被测出来&#xff0c;因为测的时候首先要去找注入的位置&#xff0c;其次是去判断第一次执行的SQL语句&#xff0c;然后还要去判断第二次进行调用的 SQL 语句。而关键问题就出在第二次的调用上面。 下面以一个常用过滤方法…

STM32学习历程(day2)

GPIO解释 GPIO(General-purpose input/output) 可以配置为八种输入输出模式 引脚电平 0V-3.3V 部分引脚可容忍5v 输出模式可控制端口输出高低电平 用以驱动LED、控制蜂鸣器、模拟通信协议输出时序 输入模式可读取端口的高低电平或电压&#xff0c;用于读取按键输入、外界…

网络IO模型之多路复用器.md

多路复用是什么&#xff1f;怎么理解&#xff1f; 本文主要涉及为 程序中处理网络IO时的模型&#xff0c;对于系统内核而言网络IO模型。这里只做普及使用 前置知识&#xff0c;什么是IO&#xff1f;怎么理解IO IO其实就是In和Out。中文翻译是输入和输出&#xff0c;只要涉及到输…

js 递归调用 相同对象--数组递归调用

<div class="save-cl"> <a-button @click="saveCl" >保存为常用策略</a-button> </div> saveCl(){ console.log(this.form.filterList[0],--------常用策略)// 此对象为上图对象 console.log(this.allElementsHaveValue(thi…

【BUUCTF-PWN】7-[第五空间2019 决赛]PWN5

参考&#xff1a;BUU pwn [第五空间2019 决赛]PWN5 //格式化字符串漏洞 - Nemuzuki - 博客园 (cnblogs.com) 格式化字符串漏洞原理详解_printf 任意内存读取-CSDN博客 32位小端排序&#xff0c;有栈溢出保护 运行效果&#xff1a; 查看main函数 存在格式化字符串漏洞 输…

Ubuntu 22.04.4 LTS 安装配置 MySQL Community Server 8.0.37 LTS

1 安装mysql-server sudo apt update sudo apt-get install mysql-server 2 启动mysql服务 sudo systemctl restart mysql.service sudo systemctl enable mysql.service #查看服务 sudo systemctl status mysql.service 3 修改mysql root密码 #默认密码为空 sudo mysql …

数据结构(3.8)——栈的应用

栈在括号匹配中的应用 流程图 代码 #include <stdio.h> #include <stdlib.h> #define MaxSize 10typedef struct {char data[MaxSize];int top; } SqStack;// 初始化栈 void InitStack(SqStack* S) {S->top -1; // 初始化栈顶指针 }// 判空 bool StackEmpty(…

在线签约如何选择?2024年10款顶级app大比拼

支持电子合同签约的10大app&#xff1a;e签宝、上上签、DocuSign、契约锁、Adobe Sign、法大大、SignNow、安心签、HelloSign、PandaDoc。 无论是企业之间的交易还是个人服务合同&#xff0c;线上电子合同签约提供了一种便捷、高效且安全的方式来处理法律文档。本文将介绍几款优…

什么是YUV和IPB,PTS和DTS,视频编码解码过程

YUV 是一种在视频处理和压缩中常用的颜色空间。 它将图像的亮度 (Y) 与色度 (U 和 V) 成分分开。 这种分离对视频压缩和广播非常有益&#xff0c; 因为人眼对亮度变化比对颜色变化更敏感。 YUV 组件简介 Y (亮度)&#xff1a;表示图像的亮度或灰度信息。U (色度)&#xff1a;…