Algoritmos y Estructuras de Datos (3)

montón

1. La estructura del montón es una estructura de árbol binario completa implementada con una matriz.
El subíndice del hijo izquierdo del nodo raíz es: 2 i+1, y el subíndice del hijo derecho es 2 i+2. El nodo padre de los dos hijos es (i-1)/2 redondeado a la baja a 2.
En un árbol binario completo, si el valor máximo de cada subárbol está en la parte superior, es una pila raíz grande
. Si el valor del nodo principal es mayor que el del nodo raíz, entonces intercambie, de lo contrario, detenga la comparación ascendente 3,
en el árbol binario completo, si el valor mínimo de cada subárbol está en En la parte superior, el montón raíz pequeño es
opuesto al montón raíz grande
4, heapInsert y heapify de la estructura del montón operan
en la raíz grande La comparación entre el montón y el montón raíz pequeño es el proceso de heapInsert;
el código de demostración de la montón de raíz grande heapInsert:

void heapify(vector<int> &a, int index)
{
    
    
	while (a[index] > a[(index - 1) / 2])
	{
    
    
		//两个元素互换
		swap(a, a[index], a[(index - 1) / 2]);
		//向上反馈
		index = (index - 1) / 2;
	}
}

Operación Heapify:
aquí hay un ejemplo, cuando el usuario desea eliminar el valor máximo en el montón raíz grande, primero debemos sobrescribir el último número en la matriz a la posición 0 en la matriz, y luego el nodo raíz comienza a comparar con el valor mínimo de los dos nodos de cotiledón Swap, y luego compare e intercambie el nodo raíz reemplazado con los dos nodos de cotiledón en la posición actual después de ser intercambiados.

void heapify(vector<int> &a, int index, int heapsize)
{
    
    
	//index表示从何位置开始进行heapify操作操作
	//heapsize表示数组的长度
	//设置左孩子的下标
	int left = index*2+1;
	//如果当前根节点还有叶节点,则操作
	while(left < heapsize)
	{
    
    
		//两个孩子中,谁的值大,则把下标给largest
		int largest = left + 1 < heapsize && a[left+1] > a[left]? left+1 : left;
		//父和孩子之间的最大值谁最大,将下标给largest
		largest = a[largest] > a[index] ? largest :index;
		
		//如果最大值就是根节点,则退出
		if(largest == index)
			break;
		
		//否则则交换
		swap(a, index, largest);
		index = largest;
		left = index*2+1;
	}
}

Dos, ordenación en montón

Ideas:
1. Organice la matriz en una estructura de montón y forme un gran montón raíz a través de la operación heapInsert
2. Intercambie el nodo en la posición 0 del gran montón raíz con el último nodo, reduzca el tamaño del montón en 1 y coloque el último elemento en el montón en la posición 0, realice la operación heapify
3. Repita el paso 2 hasta que el tamaño del montón sea 0, y la
animación de la operación final muestre:
Por favor agregue una descripción de la imagen

Código:

void heapify(vector<int>&a, int index1, int heapsize)
{
    
    

	//进行heapifty
	//设置左孩子的节点
	int left = 2 * index1 + 1;

	//如果有左孩子,则开始进行heapifty
	while (left < heapsize)
	{
    
    

		//如果有右孩子,且右孩子的数值较大,则将右孩子的下标设置为largest
		int largest = left + 1 < heapsize && a[left + 1] > a[left] ? left + 1 : left;

		//比较根节点与较大孩子的数值,如果根节点大,则跳出循环
		if (index1 == largest)
		{
    
    
			break;
		}

		//否则互换
		swap(a, index1, largest);

		//设置将最大值的下标赋值给index1,继续向下
		index1 = largest;
		left = 2 * index1 + 1;
	}
}

void heapInsert(vector<int> &a, int index)
{
    
    
	while (a[index] > a[(index - 1) / 2])
	{
    
    
		//两个元素互换
		swap(a, a[index], a[(index - 1) / 2]);

		//向上反馈
		index = (index - 1) / 2;
	}
}

void heapSort(vector<int> &a, int heapsize)
{
    
    

	if (a.size() < 2)
		return;

	//将数组构建成大根堆
	for (int i = heapsize-1; i >= 0; i--)
	{
    
    
		heapify(a, i, heapsize);
	}

	swap(a, 0, --heapsize);
	while (heapsize>0)
	{
    
    
		//将变成大根堆的根节点与数组的最后一个数互换,并且将heapsize减小1
		heapify(a, 0, heapsize);
		swap(a, 0, --heapsize);
	}	
}

3. Extensión de clasificación de almacenamiento dinámico

Se conoce una matriz casi ordenada.Casi ordenada significa que si la matriz está ordenada, cada elemento no puede moverse más de k, y k es relativamente pequeño en comparación con la matriz. Elija un algoritmo de clasificación adecuado para clasificar estos datos.
Primero construimos un montón raíz pequeño con k elementos, porque la distancia de movimiento máxima es k, por lo que en casos extremos, use este método para poner el nodo raíz del montón raíz pequeño, es decir, el valor mínimo en 0, y luego apunte Luego, muévase una posición y luego coloque el elemento k en la matriz de abajo en el montón raíz pequeño para formar un montón raíz pequeño nuevamente, y así sucesivamente. Finalmente, muestre los números en el montón raíz pequeño de pequeño a grande.
En C++, la capa inferior de la operación multiconjunto es la estructura del árbol binario.

void SortArrayDistanceLessK(vector<int> &a, int k)
{
    
    
	//定义一个multiset容器
	multiset<int> s;

	//设置遍历的起始点
	int index = 0;

	//防止k超过数组长度,要限制传入multiset容器的元素数量
	int c = a.size();
	int b = min(c, k);
	for (; index <= b; index++)
	{
    
    
		//将数组的前K个数依次传到multiset容器中
		s.insert(a[index]);
	}

	int i = 0;
	//依次将K后面的元素传入multiset容器中,并弹出第一个元素
	for (; index < a.size(); index++)
	{
    
    
		//将k之后的元素一个一个压入到multiset中
		s.insert(a[index]);

		//将set的第一个元素放到数组的第一个位置,并将multiset容器第一个元素删除
		set<int>::const_iterator it = s.begin();
		a[i] = *it;

		//删除第一个元素
		s.erase(s.begin());
		i++;
	}

	//将multiset容器中的数据以此弹出
	while (!s.empty())
	{
    
    
		//将set的第一个元素放到数组的第一个位置,并将multiset容器第一个元素删除
		set<int>::const_iterator it = s.begin();
		a[i++] = *it;

		//删除第一个元素
		s.erase(s.begin());
	}
}

4. Clasificación de cubeta

Clasificación Radix:
ejemplo de código c ++

#include <cmath>

int getDigit(int x, int d)
{
    
    
	//返回所需位数的数值
	return((x / (int)pow(10, d - 1)) % 10);
}

//桶排序
void radixSort(vector<int> &a, int L, int R, int digit)
//L:要排序的左区域
//R:要排序的右区域
//digit十进制的位数
{
    
    
	 //以十为基底
	int radix = 10;
	int i = 0, j = 0;

	//设置辅助空间,其大小与数组大小一致
	int *bucket = new int[R - L + 1];

	//有多少位就进出桶多少次,开始入桶
	for (int d = 1; d <= digit; d++)
	{
    
    
		//count[0]为当前位(d位)是0的数字有多少个
		//count[1]为当前位(d位)是0-1的数字有多少个
		//count[2]为当前位(d位)是0-2的数字有多少个
		//count[i]为当前位(d位)是0-i的数字有多少个
		//申请一个辅助数组,记录上面的数据
		int *count = new int[radix];

		//将申请的内存全部附初值0
		for (int i = 0; i < radix; i++)
		{
    
    
			count[i] = 0;		
		}

		//开始入桶操作
		for (i = L; i <=R; i++)
		{
    
    
			j = getDigit(a[i], d);
			count[j]++;
		}

		//对辅助数组处理成前缀和
		for (i = 1; i < radix; i++)
		{
    
    
			count[i] = count[i] + count[i - 1];
		}

		//开始出桶操作
		for (i = R; i >= L; i--)
		{
    
    
			j = getDigit(a[i], d);
			bucket[count[j] - 1] = a[i];	
			count[j]--;
		}

		int j = 0;
		for (i = L; i <= R; i++)
		{
    
    
			a[i] = bucket[j];
			j++;
		}
	}
}

int maxbits(vector<int> &a)
{
    
    
	//定义一个最大数值暂存变量
	int largest = 0;
	for (int i = 0; i < a.size(); i++)
	{
    
    
		largest = max(largest, a[i]);
	}

	//开始计算最大数值的十进制数一共有多少位
	int res = 0;
	while (largest != 0)
	{
    
    
		res++;
		largest /= 10;
	}
	return res;
}


void radixSort(vector<int> &a)
{
    
    
	if (a.size() < 2)
		return;
	radixSort(a, 0, a.size() - 1, maxbits(a));

}

5. La estabilidad y el resumen del algoritmo de clasificación.

Entre individuos del mismo valor, si el orden relativo no cambia debido a la clasificación, la clasificación es estable; de ​​lo contrario, no lo es.
Clasificación sin estabilidad:
clasificación de selección, clasificación rápida, clasificación de montón
clasificación con estabilidad:
clasificación de burbuja, clasificación de inserción, clasificación de combinación, clasificación bajo la idea de clasificación de cada cubeta
hasta ahora no se ha encontrado Complejidad de tiempo O(N*logN ) , complejidad de espacio adicional 0(1) y clasificación estable.
inserte la descripción de la imagen aquí¡Aviso!
1. La complejidad de espacio adicional de la clasificación por combinación puede ser O (1), pero es muy difícil y no es necesario dominarla. Si está interesado, puede buscar "método de caché interno de clasificación por combinación".

2. La "clasificación de combinación en el lugar" hará que la complejidad de tiempo de la clasificación de combinación se vuelva o(N^2
) 3. La clasificación rápida puede resolver problemas de estabilidad, pero es muy difícil y no necesita dominarla. busque "01stable sort"
4 , todas las mejoras no son importantes, porque no hay complejidad de tiempo 0(N*logN), complejidad de espacio adicional 0(1) y clasificación estable.
5. Hay una pregunta que coloca números impares en el lado izquierdo de la matriz y números pares en el lado derecho de la matriz, y requiere que el orden relativo original permanezca sin cambios. Es muy difícil encontrar este problema.

Supongo que te gusta

Origin blog.csdn.net/qq_52302919/article/details/131037538
Recomendado
Clasificación