본문 바로가기

C언어/자료구조

6-2장 버블 정렬

1. 버블 정렬 알아보기 

 

버블 정렬(bubble sort)

- 이웃한 두 요소의 대소관계를 비교하여 교환을 반복

 

ex) 배열 {6,4,3,7,1,9,8} 오름차순 정렬

- 왼쪽에 있는 값이 오른쪽에 있는 값보다 작아야 함

- 요소의 개수가 n개인 배열에서 n-1회 비교, 교환을 하면 오름차순으로 정렬됨

- 패스(pass) : 일련의 과정(비교, 교환 과정)

 

- 버블 정렬의 첫 번째 패스 

 

 

 - 버블 정렬의 두번째 패스 

- 패스를 1회 수행할 때마다 정렬할 요소가 하나씩 줄어듬

- 패스를 k회 수행하면 앞쪽의 요소가 k개 정렬됨

- 모든 정렬이 끝나려면 n-1회의 패스가 수행되어야 함

 

- 버블정렬 프로그램

//버블 정렬 (버전1)
#include <stdio.h> 
#include <stdlib.h>
#define swap(type,x,y) do {type t=x; x=y; y=t;} while(0)

//버블 정렬
void bubble(int a[], int n) 
{
	for(int i=0; i<n-1; i++) {
		//변수 i값을 0부터 n-2까지 1씩 증가하며 n-1회의 패스를 수행
		//끝에서 부터 앞쪽으로 스캔하면서 이웃하는 두 요소를 비교하고 교환 
		for(int j=n-1; j>i; j--) 
			if(a[j-1]>a[j])
				swap(int,a[j-1],a[j]);
	}
}

int main()
{
	int nx;
	
	puts("버블 정렬");
	printf("요소 개수:");
	scanf("%d",&nx);
	int *x=(int*)calloc(nx, sizeof(int));
	
	for(int i=0; i<nx; i++)
	{
		printf("x[%d]:",i);
		scanf("%d",&x[i]);
	}
	
	bubble(x,nx); //배열 x를 버블 정렬
	
	puts("오름차순으로 정렬했습니다.");
	for(int i=0; i<nx; i++)
		printf("x[%d]=%d",i,x[i]);
		
	free(x); //배열 해제 
	
	return 0; 
}

 

1.1 알고리즘 개선 (1)

 

- 이미 배열이 정렬을 마친 상태라면 그 이후의 패스는 요소 교환을 하지 않음 

- 어떤 패스에서 요소의 교환횟수가 0이면 더 이상 정렬할 요소가 없음을 뜻함

 -> 정렬작업 '멈춤' 

 

- 버블 정렬의 세번째 패스 

 

- 버블 정렬 프로그램 ( 교환횟수에 따라 정렬 작업을 멈춤)

//버블 정렬(버전 2: 교환 횟수에 따라 정렬 작업을 멈춤)
 void bubble(int a[],int n)
 {
	for(int i=0; i<n-1; i++) {
		int exchg =0; //패스에서 시도한 교환횟수
		for(int j=n-1; j>i; j--) 
			if(a[j-1]>a[j]) {
				swap(int,a[j-1],a[j]);
				exchg++;
			}
		if(exchg==0) break; //교환이 수행되지 않았다면 정렬을 멈춤  
	}
 }

- 변수 exchg

 -> 패스를 시작하기 전에 0으로 초기화 

 -> 패스에서 요소를 교환할 때마다 1씩 증가 

 -> 패스를 마쳤을 때의 exchg값 == 한 번의 패스에서 시도한 교환 횟수 

 -> exchg=0이면 정렬을 마친것이므로 break문으로 함수 종료 

 

 

1.2 알고리즘 개선(2)

 

- 배열 {1,3,9,4,7,8,6}에 대해서 버블 정렬

 - 마지막 교환 이후의 {1,3,4}는 정렬을 마친 상태 

 - 어떤 시점 이후의 교환이 수행되지 않는 다면 그보다 앞쪽의 요소는 이미 정렬을 마친 상태 

 - 두번째 패스는 나머지 4개의 요소에 대해서만 비교, 교환 수행하면됨

 

- 버블 정렬 프로그램 (스캔 범위를 제한)

//버블 정렬 (버전 3: 스캔 범위를 제한)
void bubble(int a[], int n) 
{
	int k=0; //a[k]보다 앞쪽의 요소는 정렬을 마친 상태 
	while(k<n-1) {
		int last = n-1; //마지막으로 교환을 수행한 위치를 저장
		for(int j=n-1;j<k;j--) 
			if(a[j-1]>a[j]) {
				swap(int,a[j-1],a[j]);
				last=j;
			}
		k=last;
	} 	
}

 

 - 교환을 수행할 때마다 오른쪽 요소의 인덱스 값을 last에 저장 

 - 패스를 마친 시점에 last에는 마지막으로 교환한 두 요소 가운데 오른족 요소의 인덱스가 저장 

 - last값을 k에 대입하여 다음에 수행할 패스의 범위를 a[k]까지로 제한 

  -> 다음 패스에서 마지막으로 비교할 두 요소는 a[k]와 a[k+1]이 됨

 

'C언어 > 자료구조' 카테고리의 다른 글

6-4장 단순 삽입 정렬  (0) 2023.07.28
6-3장 단순 선택 정렬  (0) 2023.07.28
6-1장 정렬  (0) 2023.07.28
5-4장 8퀸 문제  (0) 2023.07.28
5-3장 하노이의 탑  (0) 2023.07.27