数据结构入门——08排序

news2024/11/16 0:58:28

1.排序

1.1什么是排序

排序是一种操作,通过比较记录中的关键字,将一组数据按照特定顺序(递增或递减)排列起来。排序在计算机科学中非常重要,因为它不仅有助于数据的快速检索,还能提高其他算法的性能。

1.2稳定性

排序算法的稳定性与排序后的记录相对顺序有关。稳定性的重要性在于,当关键字相同时,保持记录的原有顺序可能会影响后续操作。例如,在某些情况下,次要关键字可能仍然是有序的,这样的排序称为稳定排序。常见的稳定排序算法包括:

  • 冒泡排序
  • 插入排序
  • 归并排序
  • 计数排序

不稳定排序则不会保证相同关键字的记录顺序不变,例如:

  • 快速排序
  • 堆排序
  • 选择排序

1.3内部排序

内部排序是指数据全部加载到内存中进行排序。这类排序算法通常在数据量较小或内存充足的情况下使用。常见的内部排序算法有:

  • 快速排序
  • 归并排序
  • 堆排序

1.3外部排序

外部排序适用于数据量大到无法完全加载到内存中的情况,这时需要使用外存(如磁盘)来存储数据。常见的外部排序方法是多路归并排序,它通过将数据分成若干个小块分别排序,然后依次合并这些已排序的小块。

2.排序算法

2.1插入排序

2.1.1算法思想

插入排序就跟玩扑克牌,当插入新牌(元素)时,跟前面已经排好序的牌(元素)依次比较,找到插入的位置后插入,如果后面有牌(元素),原来位置上的牌(元素)后移。

2.1.2算法特性

  • 时间复杂度:O(n^2)

                插入第 2 个元素时,比较 1 次。

                插入第 3 个元素时,比较 2 次。

                .........

                插入第i个元素时,比较 i−1 次。

我们在计算时间复杂度时,要考虑最坏的情况。

当我们对n个数进行插入排序的时候,会执行的总次数为:

        1+2+3+⋯+(n−1) =n(n-1)/2

这是一个等差数列求和,当n较大的时候n^2占主导地位,时间复杂度为O(n^2);

  • 空间复杂度:O(1),它是一种稳定的排序算法

2.1.3 插入排序代码实现

// 时间复杂度:O(N^2)  -- 逆序(从后向前比较插入)
// 最好 O(N) -- 顺序有序 或 接近顺序有序
void InsertSort(int* a, int n)  //从小到大排序
{
	for (int i = 0; i < n - 1; ++i)
	{
		int end = i;
		// 单趟排序:[0, end]有序 end+1位置的值,插进,保持他依旧有序
		int tmp = a[end + 1];   //新插入的元素
		while (end >= 0)
		{
			if (tmp < a[end])   //如果新插入的数据小于最后的
			{
				a[end + 1] = a[end];   //将原始最后的数据向后移动,往前找,直到到最前面。
				--end;
			}
			else
			{
				break;
			}
		}
		a[end + 1] = tmp;  //如果新插入的数据大于最后的,将这个数据放到最后面
	}
}

2.2希尔插入排序( 缩小增量排序 )

希尔排序(Shell Sort),也称为缩小增量排序,是插入排序的一种改进版本。它通过比较和交换不相邻的元素,逐步减少数据的无序程度,最终通过标准的插入排序完成排序。希尔排序的设计目的是为了改进插入排序在处理大规模无序数据时的性能。

2.2.1算法思想

希尔排序通过将数组按一定的间隔(称为增量)分成若干组,每组内分别进行直接插入排序。随着排序的进行,逐步缩小间隔,直到间隔为 1 时,整个数组进行最后一次插入排序。这时的数组已经接近有序,因此插入排序的效率会非常高。

操作步骤

  1. 选择增量序列:选定一个增量序列 d1,d2,…,dk​,其中 dk 必须为 1。常见的增量序列有
  2. 分组排序:对于每一个增量 di​,将待排序数组分成若干个间隔为 di的子序列,对每个子序列进行插入排序。
  3. 缩小增量:逐步缩小增量,重复上述分组排序的过程,直到增量为 1。

2.2.2算法特性

  • 时间复杂度:O(n^1.3~n^2)

                增量序列的选择对希尔排序的时间复杂度有着决定性的影响。

                不同的增量序列会导致不同的比较和交换次数,从而影响算法的整体效率。

                希尔增量序列

                每一个增量序列的长度为

                                           

                对每个子序列执行插入排序的时间复杂度大约为:

                                 

                由于有 gap 个子序列,因此在增量为 gapgapgap 时,总的时间复杂度为:

                           

                总时间复杂度是所有增量下的时间复杂度之和:

                 

              

                这个和式是一个等比数列,前 log⁡2n项的和可以近似为:

                

                因此,总的时间复杂度可以近似为:

                

  • 空间复杂度:O(1),它是一种稳定的排序算法

2.2.3希尔排序代码实现

void ShellSort(int* a, int n)
{
	// 1、gap > 1  预排序
	// 2、gap == 1 直接插入排序
	int gap = n;
	while (gap > 1)
	{
		//gap = gap/2;
		gap = gap / 3 + 1;
        //***************这部分就是插入排序************start
		for (int i = 0; i < n - gap; ++i)
		{
			int end = i;
			int tmp = a[end + gap];
			while (end >= 0)
			{
				if (tmp < a[end])
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			a[end + gap] = tmp;
		}
        //***************这部分就是插入排序************end
	}
}

2.3直接选择排序

2.3.1算法思想

直接选择排序(Selection Sort)是一种简单直观的排序算法。它的基本思想是每一趟从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。

直接选择排序的基本步骤

  1. 初始未排序区间:从数组的第一个元素开始,逐步减少未排序区间的长度。

  2. 找到最小值:在未排序区间中找到最小值(或最大值)。

  3. 交换位置:将最小值(或最大值)与未排序区间的第一个元素交换。

  4. 缩小未排序区间:重复上述步骤,直到未排序区间只剩下一个元素,此时数组已排序。

2.3.2算法特性

  • 时间复杂度:直接选择排序的时间复杂度为O(n^2)。具体分析如下:

            外层循环运行 n−1次。

                循环在第一次执行时运行 n−1次,第二次执行时运行 n−2,依此类推,总共进行比较的次数为 n+(n-1)+...+1次。因此,总的时间复杂度为 O(n^2)。

  • 空间复杂度:直接选择排序是一种原地排序算法,它只需要常数级别的辅助空间,因此空间复杂度为 O(1)。

  • 稳定性:直接选择排序是一种不稳定排序算法。例如,当数组中有两个相同的元素时,可能会在排序过程中改变它们的相对位置。

2.3.3算法代码实现

void SelectionSort(int arr[], int n) {
    for (int i = 0; i < n - 1; i++) {
        // 假设当前 i 位置上的元素为未排序区间的最小值
        int minIndex = i;

        // 在未排序区间中找到最小值的索引
        for (int j = i + 1; j < n; j++) {
            if (arr[j] < arr[minIndex]) {
                minIndex = j;
            }
        }

        // 将未排序区间的最小值与当前 i 位置的元素交换
        if (minIndex != i) {
            int temp = arr[i];
            arr[i] = arr[minIndex];
            arr[minIndex] = temp;
        }
    }
}



//改进的选择排序,通过在每次迭代中同时选择最小值和最大值并将它们放在各自的正确位置来减少排序的轮数。
void Swap(int* pa, int* pb)
{
	int tmp = *pa;
	*pa = *pb;
	*pb = tmp;
}



void SelectSort(int* a, int n)
{
	int left = 0, right = n- 1;
	while (left < right)
	{
		int mini = left, maxi = left;
		for (int i = left+1; i <= right; ++i)
		{
			if (a[i] < a[mini])
			{
				mini = i;
			}

			if (a[i] > a[maxi])
			{
				maxi = i;
			}
		}

		Swap(&a[left], &a[mini]);
		// 如果left和maxi重叠,修正一下maxi即可
		if (left == maxi)
			maxi = mini;

		Swap(&a[right], &a[maxi]);

		left++;
		right--;
	}
}

2.4堆选择排序

堆排序(Heap Sort)是一种利用堆这种数据结构进行排序的算法。堆是一种特殊的完全二叉树,有最大堆和最小堆两种类型。堆排序的核心思想是利用堆的性质来高效地进行排序。

堆的定义

  • 最大堆(Max-Heap):在最大堆中,任意节点的值都不小于其子节点的值,因此根节点的值是最大值。
  • 最小堆(Min-Heap):在最小堆中,任意节点的值都不大于其子节点的值,因此根节点的值是最小值。

2.4.1算法思想

排升序建大堆,排降序建小堆。

堆排序的基本步骤包括两个主要阶段:(以大堆为例)

  1. 构建初始堆:将无序数组构建成一个最大堆。
  2. 排序过程
    • 将最大堆的根节点(即最大值)与堆的最后一个元素交换,将最大值移到已排序区域。
    • 调整堆,使剩余部分重新满足最大堆的性质。
    • 重复上述步骤,直到堆为空。

2.4.2算法特性

  • 时间复杂度

                构建最大堆:将无序数组转化为最大堆的时间复杂度为 O(n)。

                堆调整:每次从根节点提取最大值并重新调整堆的时间复杂度为 O(log⁡n)。在整个排序过

                              程中需要执行 n次,因此总时间复杂度为 O(nlog⁡n)。

  • 空间复杂度:堆排序是原地排序算法,不需要额外的空间进行排序,空间复杂度为 O(1)。
  • 稳定性:堆排序是一种不稳定的排序算法,因为在调整堆的过程中,可能会改变相同元素的相对位置。

2.4.3算法代码实现

void AdjustDown(int* a, size_t size, size_t root)
{
	size_t parent = root;
	size_t child = parent * 2 + 1;
	while (child < size)
	{
		// 1、选出左右孩子中小的那个
		if (child + 1 < size && a[child + 1] > a[child])
		{
			++child;
		}

		// 2、如果孩子小于父亲,则交换,并继续往下调整
		if (a[child] > a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}


void HeapSort(int* a, int n)
{
	
	// 向下调整--建堆 O(N)
	for (int i = (n -1) /2; i >= 0; --i)
	{
		AdjustDown(a, n, i);
	}

	size_t end = n - 1;
	while (end > 0)
	{
		Swap(&a[0], &a[end]);
		AdjustDown(a, end, 0);
		--end;
	}
}



2.5冒泡交换排序

2.5.1算法思想

冒泡排序的基本思想是:

  • 依次比较相邻的两个元素,如果它们的顺序错误(即前一个比后一个大),则交换它们。
  • 每一轮操作后,当前轮次中最大的元素会“冒泡”到列表的最后一个位置。
  • 随着排序的进行,每轮操作后不需要比较的元素数量逐渐减少。

2.5.2算法特性

  • 时间复杂度

                     时间复杂度为 O(n^2)。

  • 空间复杂度:冒泡排序是原地排序算法,不需要额外的空间,空间复杂度为 O(1)。

                      冒泡排序是稳定的排序算法,因为在元素相等时,它不会改变相等元素的相对位置。

2.5.3算法代码实现

void Swap(int* pa, int* pb)
{
	int tmp = *pa;
	*pa = *pb;
	*pb = tmp;
}

//这里进行改进,如果一轮循环都没有交换位置,则说明已经排好顺序了
void BubbleSort(int* a, int n)  
{
	for (int j = 0; j < n; ++j)
	{
		int exchange = 0;
		// 单趟
		for (int i = 1; i < n-j; ++i) //每次找到一个最大的
		{
			if (a[i - 1] > a[i])
			{
				exchange = 1;
				Swap(&a[i - 1], &a[i]);
			}
		}

		if (exchange == 0)
		{
			break;
		}
	}
}

2.6快速交换排序(快排)

快速排序(Quick Sort)是一种高效的排序算法,采用了分治法的策略。它通过选择一个基准元素(pivot),将数组分成两部分:一部分包含所有小于基准元素的值,另一部分包含所有大于基准元素的值,然后递归地对这两部分进行排序。快速排序的平均时间复杂度为 O(nlog⁡n),是许多实际应用中使用的排序算法。

2.6.1算法思想

  1. 选择基准元素(Pivot):从待排序数组中选择一个元素作为基准元素。
  2. 分区(Partitioning):重新排列数组,使得所有小于基准元素的值都在基准元素的左边,所有大于基准元素的值都在基准元素的右边。基准元素最终会被放到其正确的位置。
  3. 递归排序:递归地对基准元素左边和右边的子数组进行排序。

2.6.2算法特性

  • 时间复杂度: O(nlog⁡n)。这是因为每次分区操作将数组大致分成两部分,递归深度为 log⁡n,每层的分区操作耗时为 O(n)。
  • 空间复杂度: O(log⁡n)。这是因为递归调用栈的最大深度为 log⁡n,在空间上比起归并排序的 O(n)要更高效。
  • 稳定性:快速排序是不稳定的排序算法,因为在排序过程中相同元素的相对位置可能会被改变。

2.6.3算法代码实现

分区算法
1.找中间数
int GetMidIndex(int* a, int left, int right)
{
	//int mid = (left + right) / 2;
	int mid = left + (right - left) / 2;  //找到left和right中间的位置
	// left mid right
	if (a[left] < a[mid])                 //找出 a[left] a[mid] a[right] 中的中间数的下标
	{
		if (a[mid] < a[right])
		{
			return mid;
		}
		else if (a[left] > a[right])
		{
			return left;
		}
		else
		{
			return right;
		}
	}
	else // a[left] > a[mid]
	{
		if (a[mid] > a[right])
		{
			return mid;
		}
		else if (a[left] < a[right])
		{
			return left;
		}
		else
		{
			return right;
		}
	}
}
2. Hoare 法
// hoare
int PartSort1(int* a, int left, int right)
{
	int keyi = left;             //先假设一个可以的数作为中间数
	while (left < right)         //让左边都是比a[keyi]小的数,让右边都是比a[keyi]大的数
	{
		// 找小
		while (left < right && a[right] >= a[keyi])   //从右往左开始把比a[keyi]小的数找到
			--right;

		// 找大
		while (left < right && a[left] <= a[keyi])     //从左往右开始把比a[keyi]大的数找到
			++left;

		Swap(&a[left], &a[right]);                     //进行交换
	}

	Swap(&a[keyi], &a[left]);

	return left;
}
3.挖坑法
// 挖坑法
int PartSort2(int* a, int left, int right)
{
	int key = a[left];
	// 坑位
	int pit = left;
	while (left < right)
	{
		// 右边先走,找小
		while (left < right && a[right] >= key)
		{
			--right;
		}

		a[pit] = a[right];
		pit = right;

		// 左边走,找大
		while (left < right && a[left] <= key)
		{
			++left;
		}

		a[pit] = a[left];
		pit = left;
	}

	a[pit] = key;
	return pit;
}
4.前后指针法
// 前后指针法
int PartSort3(int* a, int left, int right)
{
	//int midi = GetMidIndex(a, left, right);
	//Swap(&a[midi], &a[left]);

	int keyi = left;
	int prev = left, cur = left+1;
	while (cur <= right)
	{
		if (a[cur] < a[keyi] && a[++prev] != a[cur])
			Swap(&a[prev], &a[cur]);

		++cur;
	}
	Swap(&a[prev], &a[keyi]);

	return prev;
}
5.递归排序
// O(N*logN)

int PartSort3(int* a, int left, int right)
{
	//int midi = GetMidIndex(a, left, right);
	//Swap(&a[midi], &a[left]);

	int keyi = left;
	int prev = left, cur = left+1;
	while (cur <= right)
	{
		if (a[cur] < a[keyi] && a[++prev] != a[cur])
			Swap(&a[prev], &a[cur]);

		++cur;
	}
	Swap(&a[prev], &a[keyi]);

	return prev;
}


void QuickSort1(int* a, int begin, int end)
{
	// 子区间相等只有一个值或者不存在那么就是递归结束的子问题
	if (begin >= end)
		return;

	int keyi = PartSort3(a, begin, end);
	// [begin, keyi-1]keyi[keyi+1, end]
	QuickSort1(a, begin, keyi - 1);
	QuickSort1(a, keyi+1, end);
}
6.改进版排序
void QuickSort2(int* a, int begin, int end)
{
	// 子区间相等只有一个值或者不存在那么就是递归结束的子问题
	if (begin >= end)
		return;

	// 小区间直接插入排序控制有序
	if (end - begin + 1  <= 10)
	{
		InsertSort(a + begin, end - begin + 1);
	}
	else
	{
		int keyi = PartSort3(a, begin, end);
		// [begin, keyi-1]keyi[keyi+1, end]
		QuickSort2(a, begin, keyi - 1);
		QuickSort2(a, keyi + 1, end);
	}
}
7.利用栈创建非递归排序
// 非递归
void QuickSort3(int* a, int begin, int end)
{
	ST st;
	StackInit(&st);
	StackPush(&st, begin);
	StackPush(&st, end);

	while (!StackEmpty(&st))
	{
		int right = StackTop(&st);
		StackPop(&st);
		int left = StackTop(&st);
		StackPop(&st);

		int keyi = PartSort3(a, left, right);
		// [left,keyi-1][keyi+1,right]
		if (left < keyi-1)
		{
			StackPush(&st, left);
			StackPush(&st, keyi-1);
		}

		if (keyi + 1 < right)
		{
			StackPush(&st, keyi+1);
			StackPush(&st, right);
		}
	}

	StackDestory(&st);
}

2.7归并排序

归并排序(Merge Sort)是一种基于分治法的排序算法,其核心思想是将一个大问题分解成多个小问题,分别解决这些小问题,再将它们合并成一个大问题的解决方案。归并排序是一种稳定的排序算法,其时间复杂度为 O(nlogn)。

2.7.1算法思想

  • 分解(Divide):将待排序数组分为两个大致相等的子数组。
  • 递归排序(Conquer):对这两个子数组递归地应用归并排序。
  • 合并(Merge):将两个已排序的子数组合并成一个排序好的数组。

2.7.2算法特性

  • 时间复杂度:O(nlog⁡n)
  • 空间复杂度:O(n)O(n)O(n)

                归并排序需要额外的空间来存储临时数组,因此其空间复杂度为 O(n)。

  • 稳定性:归并排序是稳定的排序算法。稳定性意味着在排序过程中,相等的元素保持它们原有的相对顺序。

2.7.3算法代码实现

递归实现
void _MergeSort(int* a, int begin, int end, int* tmp)
{
	if (begin >= end)
		return;

	int mid = (begin + end) / 2;
	// [begin, mid][mid+1, end]
	_MergeSort(a, begin, mid, tmp);
	_MergeSort(a, mid+1, end, tmp);

	// 归并[begin, mid][mid+1, end]
	//printf("归并[%d,%d][%d,%d]\n", begin, mid, mid+1, end);
	int begin1 = begin, end1 = mid;
	int begin2 = mid+1, end2 = end;
	int index = begin;
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (a[begin1] < a[begin2])
			tmp[index++] = a[begin1++];
		else
			tmp[index++] = a[begin2++];
	}

	while (begin1 <= end1)
		tmp[index++] = a[begin1++];

	while (begin2 <= end2)
		tmp[index++] = a[begin2++];

	memcpy(a+begin, tmp+begin, (end - begin + 1)*sizeof(int));
}

void MergeSort(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int)*n);
	assert(tmp);

	_MergeSort(a, 0, n - 1, tmp);

	free(tmp);
}

非递归实现

void MergeSortNonR(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int)*n);
	int gap = 1;
	
	while (gap < n)
	{
		// 间距为gap是一组,两两归并
		for (int i = 0; i < n; i += 2 * gap)
		{
			int begin1 = i, end1 = i + gap - 1;
			int begin2 = i + gap, end2 = i + 2 * gap - 1;
			// end1 越界,修正
			if (end1 >= n)
				end1 = n - 1;

			// begin2 越界,第二个区间不存在
			if (begin2 >= n)
			{
				begin2 = n;
				end2 = n - 1;
			}

			// begin2 ok, end2越界,修正end2即可
			if (begin2 < n && end2 >= n)
				end2 = n - 1;

			// 条件断点
			if (begin1 == 8 && end1 == 9 && begin2 == 9 && end2 == 9)
			{
				int x = 0;
			}

			printf("归并[%d,%d][%d,%d]\n", begin1, end1, begin2, end2);

			int index = i;
			while (begin1 <= end1 && begin2 <= end2)
			{
				if (a[begin1] < a[begin2])
					tmp[index++] = a[begin1++];
				else
					tmp[index++] = a[begin2++];
			}

			while (begin1 <= end1)
				tmp[index++] = a[begin1++];

			while (begin2 <= end2)
				tmp[index++] = a[begin2++];
		}
		memcpy(a, tmp, n*sizeof(int));
		//PrintArray(a, n);

		gap *= 2;
	}

	free(tmp);
}

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

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

相关文章

PostgreSQL-03-入门篇-过滤数据

文章目录 1. WHEREWHERE 子句概述WHERE 子句示例1) 使用 WHERE 子句和等于运算符 () 示例2) 使用 WHERE 子句和 AND 运算符示例3) 使用 WHERE 子句和 OR 运算符示例4) 使用 WHERE 子句和 IN 运算符示例5) 使用 WHERE 子句和 LIKE 运算符示例6) 将 WHERE 子句与 BETWEEN 运算符一…

自动化运维---ansible

ansible是一种由Python开发的自动化运维工具&#xff0c;集合了众多运维工具&#xff08;puppet、cfengine、chef、func、fabric&#xff09;的优点&#xff0c;实现了批量系统配置、批量程序部署、批量运行命令等功能。 特点: 部署简单 默认使用ssh进行管理&#xff0c;基于py…

【LLM大模型论文日更】| 大型语言模型用于模拟搜索用户行为

论文&#xff1a;https://arxiv.org/pdf/2403.09142代码&#xff1a;未开源机构&#xff1a;中国人民大学高瓴人工智能研究院领域&#xff1a;信息检索发表&#xff1a;SIGIR2024 短文 Abstract 由于成本效益和可再现性方面的优势&#xff0c;用户模拟已成为信息检索系统面向用…

Python酷库之旅-第三方库Pandas(084)

目录 一、用法精讲 351、pandas.Series.str.isdigit方法 351-1、语法 351-2、参数 351-3、功能 351-4、返回值 351-5、说明 351-6、用法 351-6-1、数据准备 351-6-2、代码示例 351-6-3、结果输出 352、pandas.Series.str.isspace方法 352-1、语法 352-2、参数 3…

【 亿邦动力网-注册安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞 …

钢铁百科:美标A633GrC材质分析、A633GrC正火状态、A633GrC材料性能

A633GrC钢板是一种美国ASTM标准的高强度低合金结构钢板&#xff0c;字母"A"代表钢&#xff08;Steel&#xff09;&#xff0c;数字"633"表示该材料的牌号&#xff0c;而"GrC"表示该材料为高强度低合金钢&#xff08;High Strength Low Alloy&…

wtv-next 宝塔更新教程

数据库升级办法 输入用户名密码&#xff0c;点执行 程序升级办法 文件后缀看清楚&#xff0c;是amd64、arm64。etc 目录下是配置文件&#xff0c;按照格式往下加就行。 回到刚才那个页面 先点停止&#xff0c;再点启动

【大模型部署及其应用 】RAG检索技术和生成模型的应用程序架构:RAG 使用 Meta AI 的 Llama 3

目录 RAG检索技术和生成模型的应用程序架构1. **基本概念**2. **工作原理**3. **RAG的优势**4. **常见应用场景**5. **RAG的挑战**6. **技术实现**参考RAG 使用 Meta AI 的 Llama 3亲自尝试运行主笔记本与文档应用聊天关键架构组件1. 自定义知识库2. 分块3. 嵌入模型4. 矢量数据…

GAMES104:08游戏引擎的动画技术基础-学习笔记

文章目录 一&#xff0c;动画技术简介动画技术的挑战 二&#xff0c;2D游戏动画技术2.1 精灵动画&#xff08;sprite animation&#xff09;2.2 Live2D 三&#xff0c;3D游戏动画技术3.1 基于层次的刚体动画3.2 顶点动画3.3 Morph Target Animation3.4 蒙皮动画3.4.1 2D蒙皮动画…

房产系统源码开发

一、开发需求&#xff1a; 信息录入与管理&#xff1a;系统需要支持各种数据的录入&#xff0c;这包括但不限于客户信息、房源信息、员工信息、合同信息和财务信息等。这些数据是房产系统的基础&#xff0c;对于后续的信息查询、分析和共享至关重要。信息查询与检索&#xff1…

Ports Number of field profile samples 参数设置

Ports Number of field profile samples 参数设置 正文正文 在进行 Port 仿真时,通常我们会对 port 端口中的光束模式进行设定,很多时候我们会遇到一个名为 Number of field profile samples 的参数,如下图所示: 如果去官方论坛查看解释,往往会被搞得云里雾里。这个参数…

什么是AR、VR、MR、XR?

时代背景 近年来随着计算机图形学、显示技术等的发展&#xff0c;视觉虚拟化技术得到了广泛的发展&#xff0c;并且越来越普及化&#xff0c;慢慢的也走入人们的视野。目前市场上视觉虚拟化技术的主流分为这几种 VR、AR、MR、XR。这几项技术并不是最近才出现的&#xff0c;VR的…

RabbitMQ 的工作原理

下面是rabbitmq 的工作原理图解 1、客户端连接到消息队列服务器&#xff0c;打开一个channel。 2、客户端声明一个exchange&#xff0c;并设置相关属性。 3、客户端声明一个queue&#xff0c;并设置相关属性。 4、客户端使用routing key&#xff0c; 在exchange和queue 之间…

FreeBSD 针对OpenSSH 高危漏洞发布紧急补丁

近日&#xff0c;FreeBSD 项目的维护者针对OpenSSH 高危漏洞发布了紧急补丁。该漏洞被追踪为 CVE-2024-7589&#xff0c;CVSS 得分为 7.4&#xff08;最高分为 10.0&#xff09;。通过利用该漏洞&#xff0c;黑客能够在权限提升的情况下远程执行任意代码。 根据上周发布的一份…

Hive3:常用的虚拟列(Virtual Columns)

一、作用 虚拟列是Hive内置的可以在查询语句中使用的特殊标记&#xff0c;可以查询数据本身的详细参数。 Hive目前可用3个虚拟列&#xff1a; INPUT__FILE__NAME&#xff1a;显示数据行所在的具体文件BLOCK__OFFSET__INSIDE__FILE&#xff1a;显示数据行所在文件的偏移量ROW…

HarmonyOS开发:跨应用数据共享详解

目录 前言跨应用数据共享的重要性HarmonyOS的数据共享能力相关的基本概念跨应用数据共享的数据管理具体实现跨应用数据共享延伸&#xff1a;数据共享的安全和隐私结语 前言 现在的移动操作系统中&#xff0c;应用之间的数据共享已成为提升用户体验和实现功能互补的重要手段&a…

机器学习——第十四章 概率图模型

目录 14.1 隐马尔可夫模型 14.2 马尔可夫随机场 14.3 条件随机场 14.4学习与推断 14.4.1 变量消去 14.4.2 信念传播 14.5 近似推断 14.5.1 MCMC采样 14.5.2 变分推断 14.6 话题模型 14.1 隐马尔可夫模型 隐马尔可夫模型&#xff08;Hidden Markov Model&#x…

入门 MySQL 数据库:基础指南

简介 MySQL 是一个非常流行的开源关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;广泛用于 Web 应用、企业应用和数据仓库。本博客将引导你从零开始&#xff0c;学习 MySQL 数据库的基础知识。 什么是 MySQL&#xff1f; MySQL 是一个基于 SQL&#xff08;Str…

秒懂Linux之制作简易shell

目录 一.全部代码 二.自定义shell 一.全部代码 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h>#define SIZE 1024 #define MAX_ARGC 64 #define SEP &…

pnpm【实用教程】2024最新版

pnpm 简介 pnpm 全称 performant npm&#xff0c;即高性能的 npm&#xff0c;由 npm/yarn 衍生而来&#xff0c;解决了 npm/yarn 内部潜在的 bug&#xff0c;极大的优化了性能&#xff0c;扩展了使用场景&#xff0c;被誉为 最先进的包管理工具 安装 pnpm npm i -g pnpm使用 pn…