IT/JAVA

[JAVA] 배열, 함수, 삽입정렬

_KH_ 2025. 1. 8. 18:30

오늘은 배열의 값을 랜덤으로 생성하고 삽입정렬을 통해 오름차순/내림차순으로 정렬하는 프로그램을 작성하였다.

 

[한글코딩]

시작 안내문 함수() {
	      삽입정렬 프로그램을 시작합니다! 출력
	   }


	   자료형 선택 함수() {

	      스캐너 선언
	      입력 저장할 변수 선언

	      언제 올바르게 입력할지 모르므로 무한루프 {
	         자료형을 선택해주세요! (char(문자)/int(정수)) 라고 출력
	         (c 혹은 i 입력 >> ) 라고 출력
	         입력받기

	         만약(금지어 함수()) {
	            대문자를 소문자로 변환
	            탈출
	         }
	         다시 입력해주세요!
	      }
	      입력값 리턴
	   }



	   금지어 함수(입력 저장할 변수) {

	      금지어를 담을 배열 선언 및 값 저장
	      진위형 변수 선언 = 거짓으로 초기화

	      반복-배열 크기만큼 돌면서 {
	         만약(배열과 겹치는 값이 있다면) {
	            진위형 변수 = 참
	                  탈출
	         } 
	      }
	      변수 반환
	   }

	   
	   랜덤 배열 생성 함수(배열 변수) {

	      랜덤 변수 선언

	      반복문-배열 크기만큼{
	         문자라면{
	            랜덤값(65~90) 값 저장
	         }
	         숫자라면{
	            랜덤 값 저장
	         }
	      }
	   }
	   
	   
	   배열 전체 출력 함수(배열, 자료형 선택 변수) {
		   배열 복사체 출력
		   만약(c면) {
			   문자형으로 변환해서 출력
		   }   
		   아니라면 {
			   숫자 출력
	   }

	   차순 입력 함수() {

	      스캐너 선언
	      차순 저장 변수 선언

	      몇번만에 옳게 입력할지 모른다-무한루프{
	         차순을 선택해주세요! (1. 오름차순 / 2. 내림차순) 출력 
	         (숫자로 입력해주세요! >>) 출력
	         사용자 입력 받기

	         옳게 입력했다면{
	            탈출
	         }
	         에러 안내
	      }
	      입력받은 차순 반환
	   }



	   // 이하 삽입정렬 함수들
	   /*
	    * 차순별로 배열을 정렬하는 함수
	    */
	    함수 보이드형 삽입정렬(정수 차순, 배열) {
	      삽입정렬이라 위치가 1부터 시작, 횟수가 분명하기에 반복문 사용{
	         변수 키값 선언
	         하위 반복 인덱스 선언
	         횟수가 분명하기에 반복문 사용{
	            만약(차순별정렬(차순, 키값, 하위 반복문의 현재 인덱스, 배열) 함수호출) { // 거짓이면 탈출
	               탈출
	            }
	            비교값 저장
	         }
	         키값을 저장
	         배열 전체 출력 함수(배열, 자료형 선택 변수)
	      }
	   }
	    
	      /**
	       * 차순에 따라서 키값과 배열의 현재값을 비교한
	       * 배열의 다음값과 키값을 비교해야하면 참을 반환하고
	       * 더 이상 비교할 필요가 없으면 거짓을 반환한다
	       */
	      함수 진위형 차순별정렬(정수 차순, 정수 키값, 정수 배열의 현재위치, 배열) {
	         만약 (오름차순이면서 키값이 더 크다면) { //누가큰지 호출
	            반환 참
	         }
	         만약 (내림차순이면서 키값이 더 작다면) {
	            반환 참
	         }
	         반환 거짓;
	      }

	      /**
	       * 정수1과 정수 2중에서 큰 값을 반환 
	       */
	      함수 정수형 누가큰지(정수1, 정수2) {
	         반환 정수1이 정수2보다 크다면 정수1 아니면 정수2
	      }
	      
	      
	    }
	    
	    종료인사 함수() {
	       삽입정렬 프로그램을 종료합니다! 출력
	    }


	    


	    public static void main(String[] args) {

	       시작 안내문 함수();

	       자료형 선택 변수 선언 및 자료형 선택 함수() 초기화 
	       
	       배열 크기 상수 선언
	       배열 선언

	       랜덤 배열 생성 함수(배열 변수);
	       배열 전체 출력 함수(배열, 자료형 선택 변수)
	       
	       
	       삽입정렬(차순 입력 함수(), 배열); 함수 호출 

	       
	       
	       종료인사 함수();
	    }

	}

 

함수는 9개 생성하였다.

함수화 부분 한글 코딩하는데 로직이 쉽게 떠오르지 않는다 ㅠㅠ 

이번주 목표는 한글 코딩을 그대로 코드로 바꾸면 바로 작동시킬 수 있도록 정확한 한글 코딩하기!!

자꾸 코드를 설명하려는 식의 한글 코딩을 하게 되는 것 같다. 코드를 한글로 먼저 작성하는 것이지 한글 설명을 달고자 하는게 아닌데..

 

[작성 코드]

public class Test {

	public static void hello() { //시작 안내문 함수() {
	      System.out.println("삽입정렬 프로그램을 시작합니다."); // 삽입정렬 프로그램을 시작합니다! 출력
	   }

	   public static void bye() { // 종료인사 함수()
	      System.out.println("삽입정렬이 완료! 프로그램을 종료합니다."); //삽입정렬 프로그램을 종료합니다! 출력
	   }

	   public static String inputDataType() { // 자료형 선택 함수
	      Scanner sc = new Scanner(System.in); // 스캐너 변수 선언
	      String dataType; //   입력 저장할 변수 선언

	      while(true) { // 언제 올바르게 입력할지 모르므로 무한루프
	         System.out.println("원하시는 자료형을 선택해주세요! ( char=문자 / int=정수 )"); // 자료형을 선택해주세요! (char(문자)/int(정수)) 라고 출력
	         System.out.println("=====================");
	         System.out.print("c 혹은 i를 입력해주세요 >> "); // (c 혹은 i 입력 >> ) 라고 출력
	         dataType = sc.next(); // 입력받기
	         System.out.println("=====================");

	         if(hasInputDataType(dataType)) { // 만약(금지어 함수())
	            dataType = dataType.toLowerCase(); // 대문자를 소문자로 변환
	            break; // 탈출
	         }
	         System.out.println("옳지 않은 입력입니다! 다시 입력해주세요."); // 다시 입력해주세요!
	      }
	      System.out.println(); // 줄바꿈

	      return dataType; // 입력값 리턴
	   }

	   public static boolean hasInputDataType(String dataType) { // 금지어 함수(입력 저장할 변수)
	      String[] checkDatas = new String[4]; // 금지어를 담을 배열 선언 및 값 저장
	      checkDatas[0]= "c";
	      checkDatas[1]= "C";
	      checkDatas[2]= "i";
	      checkDatas[3]= "I";

	      boolean flag = false; // 진위형 변수 선언 = 거짓으로 초기화

	      for(String v : checkDatas) { // 반복-배열 크기만큼 돌면서
	         if(v.equals(dataType)) { // 만약(배열과 겹치는 값이 있다면)
	            flag = true; // 진위형 변수 = 참
	            break; // 탈출
	         }
	      }

	      return flag; // 변수 반환
	   }

	   public static void printDatas(int[] datas, String dataType) { // 배열 전체 출력 함수()
	      System.out.print("배열 : [ ");
	      for(int v : datas) { // 배열 복사체 출력
	         if(dataType.equals("c")) { // c라면
	            System.out.print((char)v+" "); // 문자로 출력
	         }
	         else {
	            System.out.print(v+" "); // 숫자 출력
	         }
	      }
	      System.out.println("]");
	   }
	   
	   public static void printDatas1(int[] datas, String dataType) { // 배열 전체 출력 함수()
		      
		   System.out.print("배열 : [ ");
		      if(dataType.equals("c")) {
		    	  for(int v : datas) {
		    		  System.out.print((char)v+" "); }
		    	 
		      } else {
		    	  System.out.print(v+" "); // 숫자 출력
		      }
		      System.out.println("]");
	   }
	   

		  



	   public static int inputOrder() { // 차순을 입력받는 함수
	      Scanner sc = new Scanner(System.in); // 스캐너 변수 선언
	      // 저장변수
	      int order; // 차순을 저장할 변수 선언

	      while(true) { // 무한루프
	         System.out.println("차순을 선택해주세요! (1. 오름차순 / 2. 내림차순)");
	         System.out.print("숫자로 입력해주세요! >>");
	         order = sc.nextInt(); // 숫자로 입력받음

	         if(order  == 1 || order  == 2) { // 옳은 답을 입력하면 탈출
	            break;
	         }
	         System.out.println("올바른 숫자를 입력해주세요!"); // 에러 메시지
	      }
	      return order; // 입력한 차순 반환
	   }


	   public static void createList(int[] datas, String dataType) { // 랜덤 배열 생성 함수(배열, 문자열)

	      Random rand = new Random(); // 랜덤 변수 선언

	      for(int i = 0; i < datas.length; i++) { //반복문-배열 크기만큼
	         if(dataType.equals("c")) { // 문자라면
	            datas[i] = rand.nextInt(26)+65; //  랜덤값(65~90) 값 저장
	         } else { // 숫자라면
	            datas[i] = rand.nextInt(21)-10; // 랜덤 값 저장
	         }
	      }   
	   }

	   /**
	    * 삽입정렬을 실행하는 함수
	    * parameters: int 차순, int[] 정렬할 배열
	    */
	   public static void insertionSort(int order, int[] datas, String dataType) { //함수 보이드형 삽입정렬(정수 차순, 배열) 
	      for (int i = 1; i < datas.length; i++) { //삽입정렬이라 위치가 1부터 시작, 횟수가 분명하기에 반복문 사용{
	         int key = datas[i]; //변수 키값 선언
	         int index; //하위 반복 인덱스 선언
	         for (index = i - 1; index >= 0; index--) { //횟수가 분명하기에 반복문 사용
	            if (sortByOrder(order, key, datas[index])) { //현재 인덱스에 key가 들어가야하는 조건이라면
	               break; //탈출
	            }
	            datas[index+1] = datas[index]; //비교값 저장
	         }
	         datas[index+1] = key; //키값을 저장
	         printDatas(datas, dataType); //배열 전체 출력 함수()
	      }
	   }

	   /**
	    * 차순별로 키값과 현재값을 비교하여 종료조건에 해당하는지 아닌지를 진위형 값으로 반환하는 함수
	    * parameters:int 차순, int 키값, int 현재값
	    * return: boolean
	    */
	   public static boolean sortByOrder(int order, int key, int curVal) { //함수 진위형 차순별정렬(정수 차순, 정수 키값, 정수 배열의 현재위치, 배열) {
	      if (order == 1 && key >= curVal) { //만약 (오름차순이면서 키값이 더 크다면)
	         return true; //반환 참
	      }
	      else if (order == 2 && key <= curVal) { //만약 (내림차순이면서 키값이 더 작다면) 
	         return true; // 반환 참
	      }
	      return false; // 반환 거짓
	   }


	   public static void main(String[] args) {
	      hello(); // 시작 안내문 함수();

	      String dataType = inputDataType(); //  자료형 선택 변수 선언 및 자료형 선택 함수() 초기화

	      final int SIZE = 10; // 배열 크기 상수 선언
	      int[] datas = new int[SIZE]; //  배열 선언

	      createList(datas, dataType); //랜덤 배열 생성 함수(배열 변수);

	      int order = inputOrder(); // 함수에서 차순 입력 받아 변수에 저장
	      System.out.println("정렬 전 배열:"); 
	      printDatas(datas, dataType); // 배열 전체 출력 함수();

	      insertionSort(order, datas, dataType); // 삽입정렬

	      System.out.println("정렬 완료 후 배열:");
	      printDatas(datas, dataType); // 배열 전체 출력 함수();

	      bye(); // 종료인사 함수();
	   }
	}

 

출력 결과

 

[피드백]

1. 함수화 : 기능이 다르다고 생각하면 함수화 하기

-> 문자로 배열 채우는 경우, 정수로 채우는 경우를 하나의 함수로 함께 작성했는데 따로 두는 게 더 좋았을 것 같다는 생각이 든다.

 

2. 효율성 고려 : 데이터의 크기가 커질 경우 해당 조건문을 커진 크기만큼 더 돌기 때문이다. (연산 횟수 최소화 필요)

-> for문을 밖에 뒀는데 if문을 밖에 두고 조건에 맞는 경우에만 반복하도록 수정하면 연산 횟수를 줄일 수 있다!!

 

3. 코드 다시 확인하기 : 쓸모없는 파라미터 놔두지 말고 지우기 

-> 코드를 . 정확히. 보자. .... 제발

 

+ ) 삽입정렬.. 그림으로만 봤을 땐 키값과 앞에 있는 요소들을 비교해서 키값이 더 작을 경우 해당 요소들을 뒤로 밀어내고 키값을 삽입한다고 이해했는데, 코드를 작성할 때는 요소를 밀어낸다는 말의 의미가 그게 아니라는 점을 알았다.

그림으로 보면 밀어낸다고 하지만.. 애초에 배열에는 빈 공간이라는 게 존재하지 않아 요소를 밀어낸다고 해서 밀어낸 요소의 공간이 비어있게 되는 것이 아니라는 거다.

비어있는 공간이 아니고, 그 이전 요소를 복사해서 덮어씌우는 것이란 걸 알았다.

알고리즘 어렵다..