Autor
|
Tema: Modificar busqueda binaria (Leído 4,319 veces)
|
mari2diaz
Desconectado
Mensajes: 24
|
modifique la búsqueda binaria de manera que la función devuelva el índice del primer elemento mayor al que se está buscando y -1 en caso de que no exista ningún elemento mayor si elijo cualquier otro numero q no sea el 144 funciona el programa, no se q estoy haciendo mal o hay una mejor forma de hacerlo #include <iostream> int busquedaBinaria(int clave, int array[], int size); int main(){ int numero; int size = 15; int array[size] = {0, 1, 1, 2, 3, 5, 8, 13, 13, 21, 34, 55, 89, 144, 144}; std::cout << "Buscar numero: "; std::cin >> numero; if(busquedaBinaria(numero, array, size) > 0) std::cout << "Array[" << busquedaBinaria(numero, array, size) << "] = " << array[busquedaBinaria(numero, array, size)] << std::endl; else std::cout << "No hay elemento mayor a " << numero << std::endl; return 0; } int busquedaBinaria(int clave, int array[], int size){ int centro; int bajo = 0; int alto = size - 1; while(bajo <= alto){ centro = (bajo + alto) / 2; if(clave == array[centro]){ while(centro < (size - 1)){ if(clave < array[centro]) return centro; centro++; } }else if(clave < array[centro]) alto = centro - 1; else bajo = centro + 1; } return -1; }
|
|
|
En línea
|
|
|
|
Serapis
|
Tu problema está en el bucle while dentro de la condición de coincidencia... Pasando 144, se localiza en el penúltimo índice, le pides que localiza los que sean iguales para tratar de devolver el último de ellos con el mismo valor, hay uno más... pero en tu bucle sigues aumentando el índice sin comprobar si se alcanzó el final del array. Una mejor manera es hacer justo lo contrario (en cierto modo), devolver el índice donde debiera ubicarse si no existe, o el primer lugar donde exista. Dado que el índice 0, siempre existe, si resulta ser menor que todo el array o igual al primer elemento, devuelve 0, con lo cual siempre estará bien ubicado, y no incurres en error. Mejor aún es simplemente devolver ese índice, sin tratar de buscar los que le preceden o siguen de igual valor... ya si por ejemplo se tratara de insertar un elemento, que más da, que se inserte el primero, el 5 de 10 o el 10 (si antes eran 9). tu al final tras la inserción tendrías (por ejemplo): ...x, x, x, x 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, y, y, y, y... Cuál de esos 144 es el que tu has añadido?. No suele importar si no tiene más datos asociados. Hacer mientras (bajo <= alto) centro = (bajo + alto) / 2 si (clave < array[centro]) alto = centro - 1 osi (clave < array[centro]) bajo = centro + 1 sino // (clave = array[centro]) devolver centro fin si Repetir devolver -1
Si a pesar de todo deseas mantener tu código, lo comento en detalle... Observa el problema paso a paso... el array tiene 15 elementos que van del indice 0 al 14. Hay dos casos, que accedas primero al indice 13 o primero al indice 14... A - En el indice 13 localiza, el valor 144: luego entra en el bucle, ya que el índice 13 es menor que el size-1 del array. Ahora evalúa si el valor es menor que el recién enconttrado (en el índice 13), no es verdad luego incrementa centro y regresa a la condición del bucle... ahora se alcanzó el límite del bucle, lo que impide seguir ejecutándolo, sale del bucle y luego del externo y por tanto devuelve -1 B - En el indice 14 localiza el valor 144: El bucle while impide entrar al mismo, pues es el último en el array, sale del bucle interno y luego del externo y devuelve -1 Tú codigo funcionaría, si tras dichos valores hubiera un elemento más (mayor lógicamente que los previos). Pero entonces tendría el mismo problema con ése... es decir siempre con el último (o últimos, si son iguales). Tu código debe quedar así: while(bajo <= alto){ centro = (bajo + alto) / 2; if(clave == array[centro]){ centro++; while(centro <= (size - 1)){ if(clave < array[centro]) return centro; centro++; } return centro; }else if(clave < array[centro]) alto = centro - 1; else bajo = centro + 1; } return -1;
Nota las dos líneas (4 y 10) que he añadido y la 5 modificado.
|
|
« Última modificación: 13 Abril 2022, 01:00 am por Serapis »
|
En línea
|
|
|
|
jca1
Desconectado
Mensajes: 59
|
Esta seria otra manera Hacer mientras (bajo < alto) //(cuando bajo=alto la busqueda llega al final) centro = (bajo + alto) / 2 si(clave < array[centro]) alto = centro //(no es -1 ya que se incluye a centro porque puede ser la soulcion tambien) sino bajo = centro + 1 fin si si (clave<array[bajo]) //(al ser bajo=alto se puede usar cualquiera y es verdadero cuando existe solucion) devolver bajo sino devolver -1; //(este caso solo sucede cuando bajo=size-1 y clave>=array[bajo], o sea cuando no existe solucion) Este pseudocodigo esta generalizado para buscar el primer valor mayor a cualquier numero que utilices como dato de entrada. Es decir que no es necesario que ese numero este en el arreglo. Si tenes como premisa que el dato de entrada es un numero que se encuentra en el arreglo, que creo que es este el caso que planteaste, seria asi hacer mientras (bajo <= alto) centro = (bajo + alto) / 2 si (clave = array[centro]) hacer mientras (centro < size) si (clave < array[centro]) devolver centro centro = centro + 1 Repetir devolver -1 o si (clave < array[centro]) alto = centro sino bajo = centro + 1 repetir
La primera solucion de Serapis devuelve el indice donde esta la clave y no el siguiente mayor.
|
|
« Última modificación: 29 Mayo 2022, 13:19 pm por jca1 »
|
En línea
|
|
|
|
dijsktra
Desconectado
Mensajes: 110
Mr Edsger Dijsktra (Tribute to)
|
Te paso la original y una variación que devuelve el indice del primer número mayor y en caso contrario devuelve el tamaño del vector size . (Esto es más natural que -1..) Tu ya lo cambias si quieres. #include <iostream> int binary_search(const int V[], const int N, const int elem); int binary_search2(const int V[], const int N, const int elem); #define size 15 int main(){ int numero; int array[size] = {0, 1, 1, 2, 3, 5, 8, 13, 13, 21, 34, 55, 89, 144, 144}; std::cout << "Buscar numero: "; std::cin >> numero; const int index = binary_search2(array, size,numero); if (index == size) std::cout << "No hay elemento mayor a " << numero << std::endl; else std::cout << "Array[" << index << "] = " << array[index] << std::endl; return 0; } #define h ((i+j)/2) /* P: N >= 1, V sorted , elem in V*/ /* original */ int binary_search(const int V[], const int N, const int elem) { int i,j; i=0; j=N; while (V[h]!= elem) if (V[h]>elem) j=h; else i=h+1; return h; } /* P: N >= 1, V sorted , elem in V*/ /* Variation */ int binary_search2(const int V[], const int N, const int elem) { int i,j; i=0; j=N; // I : 0<= i < j <= N and V[i] <= V[elem] <= V[j-1] while (V[h]!= elem || (h<N-1 && V[h]==V[h+1])) // <= B: Changes. if (V[h]>elem) j=h; else i=h+1; return h+1; // V[h] points to element. }
EDIT: La linea while (V[h]!= elem || (h<N-1 && V[h]==V[h+1])) // <= B: Changes. tenía un error tipográfico. (Crédito: jca1) La salida da Buscar numero: 8 Array[7] = 13 Buscar numero: 144 No hay elemento mayor a 144
No quiero abrumar con formalismos. Fijate especialmente en: - la precondicion P: el array ordenado y el numero que pases tiene que existir
- la parada B: A la derecha de h hay uno mayor, o esta en ultima posicion
Un saludo.
|
|
« Última modificación: 2 Junio 2022, 05:45 am por dijsktra »
|
En línea
|
Si la depuración es el proceso de eliminar fallos en el software, entonces programar debe ser el proceso de ponerlos dentro. (Edsger Dijsktra)
|
|
|
jca1
Desconectado
Mensajes: 59
|
while (V[h]!= elem || (elem!=N-1 && V[h]==V[h+1])) // <= B: Changes.
La solucion que planteaste seria la correcta ya que cumple el sentido de busqueda binaria exactamente. Solo en la comparacion para verificar si estas en la ultima posicion, es "h" en vez de "elem". Si no hay valores mayores, "h" termina siendo igual a "N-1" cuando termina el ciclo y despues devuelve "h+1", que es igual al tamaño del arrreglo. Saludos.
|
|
« Última modificación: 2 Junio 2022, 04:47 am por jca1 »
|
En línea
|
|
|
|
dijsktra
Desconectado
Mensajes: 110
Mr Edsger Dijsktra (Tribute to)
|
Gracias jca1! 1000 veces lo hubiera visto y 1000 veces no me habría dado cuenta del error tipográfico. Corrijo en el original , poniendo EDIT y dando crédito.
|
|
|
En línea
|
Si la depuración es el proceso de eliminar fallos en el software, entonces programar debe ser el proceso de ponerlos dentro. (Edsger Dijsktra)
|
|
|
dijsktra
Desconectado
Mensajes: 110
Mr Edsger Dijsktra (Tribute to)
|
Si tenes como premisa que el dato de entrada es un numero que se encuentra en el arreglo, que creo que es este el caso que planteaste, seria asi hacer mientras (bajo <= alto) centro = (bajo + alto) / 2 si (clave = array[centro]) hacer mientras (centro < size) si (clave < array[centro]) devolver centro centro = centro + 1 Repetir devolver -1 o si (clave < array[centro]) alto = centro sino bajo = centro + 1 repetir
La primera solucion de Serapis devuelve el indice donde esta la clave y no el siguiente mayor. Ésta, -si fuese correcta, que depende de los valores iniciales de alto y bajo- no es efficiente como la búsqueda binaria, sino que degrada a busqueda lineal O(n)... Imagina un millon de 1´s y la ultima posición es 2... Entonces, el programa itera 500.000 veces, o sea O(N/2) = O(N). La que yo expuse, iteraría como mucho 20 (<= log_2 10^6)
|
|
« Última modificación: 2 Junio 2022, 06:22 am por dijsktra »
|
En línea
|
Si la depuración es el proceso de eliminar fallos en el software, entonces programar debe ser el proceso de ponerlos dentro. (Edsger Dijsktra)
|
|
|
jca1
Desconectado
Mensajes: 59
|
Ésta, -si fuese correcta, que depende de los valores iniciales de alto y bajo- no es efficiente como la búsqueda binaria, sino que degrada a busqueda lineal O(n)...
Si tienes razon! Me olvide de acotar que esa solucion no es eficiente por eso. No pude modificarla asi que muy bien aclarado, igual no es necesario ya. Gracias dijsktra! Este es el algoritmo referido: hacer mientras (bajo <= alto) centro = (bajo + alto) / 2 si (clave = array[centro]) hacer mientras (centro < size) si (clave < array[centro]) devolver centro centro = centro + 1 Repetir devolver -1 o si (clave < array[centro]) alto = centro sino bajo = centro + 1 repetir
Saludos!
|
|
« Última modificación: 2 Junio 2022, 21:46 pm por jca1 »
|
En línea
|
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
busqueda binaria
Programación C/C++
|
Sunshine66
|
3
|
4,682
|
6 Mayo 2010, 07:42 am
por Akai
|
|
|
Busqueda binaria con palabras
Programación C/C++
|
soez
|
0
|
3,148
|
3 Agosto 2010, 04:10 am
por soez
|
|
|
Busqueda binaria.
Java
|
NetJava
|
6
|
9,315
|
28 Marzo 2011, 18:20 pm
por NetJava
|
|
|
[C] Búsqueda binaria recursiva
Programación C/C++
|
BatchianoISpyxolo
|
3
|
19,458
|
29 Octubre 2012, 23:08 pm
por flony
|
|
|
busqueda binaria en archivo
Programación C/C++
|
m@o_614
|
5
|
5,823
|
2 Enero 2014, 00:34 am
por m@o_614
|
|