데이터 구조의 세 가지 주요 알고리즘(사례 분석)

개요

이 기사에서는 데이터 구조에서 가장 일반적으로 사용되는 세 가지 알고리즘인 분할 정복 , 동적 프로그래밍탐욕적 알고리즘에 대해 설명합니다 . 주로 이러한 알고리즘의 고전적인 사례에서 시작하여 알고리즘을 분석하고 이해합니다.

분할 및 정복

분할 정복법은 일반적으로 큰 물고기를 여러 조각으로 나누고 각 조각을 별도로 요리한 다음 접시를 만드는 것으로 이해될 수 있습니다. 즉, 분할 정복 방법은 큰 문제를 여러 개의 작은 문제로 나누고 이러한 작은 문제를 해결한 후에 전체 큰 문제를 해결할 수 있습니다. 처리 과정에서 이러한 작은 문제의 처리 방법은 다음과 같습니다. 다른. 다음 사례에서 더 분석하고 이해해 봅시다.

문제 설명

a[0:n-1]정렬된 배열이라고 가정하고 배열에 없을 때 보다 작은 최대 요소 위치 와 보다 큰 최소 요소 위치를 반환하도록 이진 검색 알고리즘을 다시 작성하십시오 . 검색 요소가 배열에 있는 경우 배열의 위치 동일합니다 .xxixjijx

알고리즘 사고 및 설계

문제를 단순화하여 n원소 집합에서 최대값과 최소값을 구하고, n이 각각 최대값과 최소값을 구합니다. 그런 다음 각 그룹의 수가 . 이하가 될 때까지 재귀적으로 분해합니다 2. 이진 검색 아이디어를 사용하여 배열에서 키워드를 찾고 x배열 의 헤드와 테일을 인덱싱합니다 low. 이때top 배열의 중간 값 과 같으면 배열에 있다는 의미로 첨자를 반환하고 , 배열의 중간값보다 크면 중간 같다 면 에 복사 하고 할당 다음 아래 첨자를 반환합니다 . 전체 코드는 다음과 같습니다.low<=topxxi,jxlow+1xtop+1lowtopxtopi,lowji,j

#include<stdio.h>
int search(int a[],int length, int x)
{
    
    
int i = 0, j = 0;
int s= -1;
int top = length - 1;
	int mid = 0;
	int low = 0;
	while (low <= top)
	{
    
    
		mid = (low + top) / 2;
		if (a[mid] == x)
		{
    
    
			s = mid;
		}
		if (a[mid] < x)
		{
    
    
			low = mid + 1;
		}
		else
		{
    
    
			top = mid - 1;
		}
	}	
	if (s == -1)
	{
    
    
		i = top;
		j = low;
	}
	else
	{
    
    
		i = s;
		j = i;
	}
	printf("%d %d",i,j);
	return 0;
}
int main()
{
    
    
	int arr[100];
	int x,n;
	scanf("%d %d",&n,&x);
	for(int i=0;i<n;i++)
	{
    
    
		scanf("%d",&arr[i]);
	}
	search(arr,n,x);
	return 0;
}

동적 프로그래밍

동적 프로그래밍 알고리즘은 종종 몇 가지 최적 속성이 있는 문제를 해결하는 데 사용됩니다. 이러한 유형의 문제에는 실행 가능한 솔루션이 많이 있을 수 있습니다. 각 솔루션은 값에 해당하며 최적의 값을 가진 솔루션을 찾고자 합니다. 동적 계획법 알고리즘은 분할 정복 방법 과 유사하며, 그 기본 개념은 해결해야 할 문제를 여러 하위 문제로 분해하고 먼저 하위 문제를 해결한 다음 솔루션에서 원래 문제의 솔루션을 얻는 것입니다. 이러한 하위 문제 중. 분할 정복 방식과 달리 동적 프로그래밍으로 해결하는 문제에 적합하며 분해를 통해 얻은 하위 문제는 서로 독립적이지 않은 경우가 많습니다.

문제 설명

주어진 n(n<=100)아이템과 배낭. 항목 i의 무게는 wi, 값은 vi, 배낭의 용량은 입니다 C(C<=1000). 질문: 배낭에 있는 항목의 총 가치를 최대화하려면 배낭에 있는 항목을 어떻게 선택해야 합니까? 짐. 항목 i는 여러 번 로드할 수 없으며 일부 항목만 로드할 수 없습니다 i.

알고리즘 사고 및 설계

동적 프로그래밍은 테이블을 채우는 과정입니다. 이제 배낭이 있고 1배낭의 용량은 이며 번호가 매겨진 항목이 10있으며 모두 자체 무게와 가격이 있습니다. 배낭의 용량을 초과하지 않고 배낭에 적재된 아이템의 가치를 극대화하기 위해 필요합니다. 문제를 다섯 가지 하위 문제로 나눌 수 있습니다. 하위 질문에 대한 답변을 테이블에 저장할 수 있습니다 . 하위 문제를 해결하려면 하위 문제의 답을 사용해야 하기 때문에( 계획의 각 단계를 계획의 각 단계와 비교해야 하며 계획의 단계가 해당 계획보다 얼마나 나은지 확인해야 합니다. 그런 다음 표시합니다 . 계획의 이 단계가 실현 가능합니다. 최적이 아닌 경우 충분하거나 문제의 제약 조건을 충족하지 않으면 솔루션을 폐기합니다. 이 단계에 해당하는 솔루션을 이 단계의 솔루션으로 계속 사용합니다. 하위 문제를 해결하려면 하위 문제에 대한 답을 사용해야 하며 하위 문제를 해결하는 것은 재귀적 이며 하위 문제에 대한 답을 사용해야 합니다. 하위 문제 는 원래 문제입니다. 하위 문제에 대한 답은 원래 문제에 대한 최종 해결책입니다. 전체 코드는 다음과 같습니다. 실험 결과51,2,3,4,51,2,3,4,5212121211325455

입력 사례:
5 10
2 6
2 3
6
5 5
4 4 6

	输出结果:15
#define EMPTY
#include<stdio.h>
#include <iostream>
using namespace std ; 
 int main()
 {
    
    
	int V ,T;
	scanf("%d %d",&T,&V);
 	int f[V+1],w[100],c[100];
 	
 	for(int m=0;m<T;m++){
    
    
	 scanf("%d",&c[m]);
 	 scanf("%d",&w[m]);
	 }
 const int INF = -66536  ;
 #ifdef EMPTY
    for(int i = 0 ; i <= V ;i++)
      f[i] = 0 ;    
 #else
    f[0] = 0 ;
    for(int i = 1 ; i <= V ;i++)
      f[i] = INF ;   
 #endif
    
    for(int i = 0 ; i < T ; i++)
    {
    
    
      for(int v = V ; v >= c[i] ;v--)
         {
    
                  
           f[v] = max(f[v-c[i]] + w[i] , f[v]);
         }                 
    }
    cout<<f[V];
    return 0;        
 }

그리디 알고리즘

그리디 알고리즘은 특정 최적 솔루션 문제에 대한 더 간단하고 빠른 설계 기법입니다. 그리디 알고리즘의 특징은 단계별로 진행된다는 점으로, 가능한 전체 상황을 모두 고려하지 않고 현재 상황에 기반한 최적화 척도를 기반으로 최적의 선택을 하는 경우가 많아 최적을 찾기 위해 모든 가능성을 소진할 필요가 없다. 솔루션 많은 시간이 낭비되었습니다. 탐욕 알고리즘은 하향식 반복 방법을 채택하여 연속적인 탐욕 선택을 합니다. 탐욕 선택이 이루어질 때마다 문제는 더 작은 하위 문제로 단순화됩니다. 탐욕 선택의 각 단계를 통해 최적의 문제를 얻을 수 있습니다 . 해결책.

문제 설명

(1<=n<=50,000)젖을 짜야 할 소는 n마리입니다 . 각 젖소가 젖을 짜는 시간 간격이 주어집니다 A,B. 젖소는 젖을 짜기 위해 목장에 머물러야 합니다. 목장은 한 번에 한 마리의 소만 담을 수 있습니다. 전체 착유 작업을 완료하는 데 필요한 최소 스톨 수를 문의하십시오. (같은 우리에 있는 두 마리의 젖소의 경우 착유 시간 간격이 끝점에서 일치할 수 없습니다.)

알고리즘 사고 및 설계

우리는 시작 시간 또는 종료 시간을 증가시켜 각 젖소의 착유 시간을 정렬할 수 있으며 이러한 시간 간격과 호환되는 가장 큰 하위 집합을 찾아 목장에 이러한 젖소를 더 일찍 배치할 수 있습니다. 정렬되지 않은 경우 시간 컬렉션의 가장 큰 하위 집합을 찾은 다음 두 번째 목장에 정렬해야 합니다. 이것은 배열이 완료될 때까지 계속되며 이러한 하위 집합의 수가 우리의 최소 수입니다. 전체 코드는 다음과 같습니다.
실험 결과

입력 샘플:

5

1 10

2 4

3 6

5 8

4 7

샘플 출력:

4

//判断区间是否重叠 
bool isOverlap(int x[999][2], int i, int j,int s[]) {
    
    
	if (x[i][0] > x[j][1] || x[i][1] < x[j][0]) {
    
    
		for (int m = j + 1; m < i; m++) {
    
    
			if (s[m] == s[j] && isOverlap(x, i, m, s))
				return true;
		}
		return false;
	}
	else
		return true;
}
//贪心 
void Greedy(int x[999][2]) {
    
    
	int s[999] = {
    
     0 };
	for (int i=0; i < 7; i++) {
    
    
		for (int j = 0; j < i; j++) {
    
    
			if (!isOverlap(x, i, j,s)) {
    
    
				s[i] = s[j];
				break;
			}
			else {
    
    
				continue;
			}
		}
		if (s[i] == 0) 
			s[i] = maxNum(s) + 1;
	}
	cout << maxNum(s)<< endl; //所需的畜栏个数
	for (int i = 0; i < 7; i++) {
    
    
		cout << s[i] << endl;//每头牛对应的畜栏
	}
}
//畜栏个数 
int maxNum(int x[]) {
    
    
	int max = x[0];
	for (int i = 1; i < 7; i++) {
    
    
		if (max < x[i]) {
    
    
			max = x[i];
		}
	}
	return max;
}

Supongo que te gusta

Origin blog.csdn.net/qq_43774332/article/details/127229302
Recomendado
Clasificación