배열 - 강원대학교

Download Report

Transcript 배열 - 강원대학교

배열
한 개의 이름을 사용하여 많은 데이터를 저장
-1-
배열(array)
•
•
같은 유형의 데이터 집합을 저장
이름을 갖는 연속적인 메모리(memory) 위치
•
하나 이상의 값을 저장할 수 있다.
•
배열은 수천 개 혹은 수백만 개의 리스트도 저장 가능.
-2-
변수와 배열의 비교
-3-
배열 선언
type[] name
type name[]


type은 int, char, double, boolean과 같은 데이터 유형
name은 배열 이름
int[] myArray
double[] yourArray:


myArray 와 yourArray 는 참조변수(reference variables)
참조 변수는 메모리 주소(memory address)를 저장한다.
-4-
배열 구성
int[] myArray;
// 선언
myArray = new int[5];
// 배열 구성
or
int[] myArray = new int[5];
// 선언과 구성
참조변수(reference)는 저장
메모리 블록의 첫 번째
셀(cell) 주소를 저장한다.
배열의 첫 번째
인덱스(index)는 0이다.
-5-
배열 구성
•
배열이 구성될 때, 각 메모리 셀은 각 데이터 타입의 기본
값으로 초기화된다.
•
•
•
int, short, long, byte, char – 0
double, float – 0.0
boolean - false
-6-
배열 구성
System.out.println("Enter array size: ");
int size = input.nextInt();
double [] decimals;
// 참조변수 선언
decimals = new double[size];
// 배열 인스턴스를 구성하고
// 그 주소를 참조변수에 저장
-7-
배열 구성
int x = 3;
char [] letters = new char[2*x];
**********
• letters는 char 데이터의 배열을 참조한다.
• 각 메모리 셀은 0으로 초기화된다.
-8-
배열 구성
• 배열이 구성되면 배열의 길이는 고정된다.
• 배열의 길이를 변경할 수 없다.
• 참조변수 x가 배열을 참조하고 있을 때,
x.length는 배열에 할당된 메모리 셀의 개수
-9-
배열 사용
• 각 메모리 셀은 변수이다.
•
•
numbers[0] = input.nextInt();
•
numbers[1] = 2 + numbers[0]; // 2 + numbers[0]을
// numbers[1]에 대입
•
System.out.println(5*numbers[1] + 3*numbers[0]);
// numbers[0]에 읽은 값을
// 저장
- 10 -
데이터 타입
논리형(logical) : boolean
기본(primitive) 타입
문자형(textual) : char(16)
정수형(integral) : byte(8), short(16), int(32), long(64)
부동소수형(floating point) :float(32), double(64)
객체 (class, interface, array)
Reference 타입
int current;
// 기본 타입 변수 current 선언
current = 100;
// currnet에 값 배정 (assign)
Counter c = new Counter();
// reference 타입 변수 c 선언 및 초기화
current
100
Counter 객체
c
강원대학교
11
Object References and Number
Variables
레퍼런스변수
Object reference
primitive 타입 (기본타입)
상태변수
강원대학교
12
숫자 복사하기
(Copying Numbers)
int luckyNumber = 13;
int luckyNumber2 = luckyNumber;
luckyNumber2 = 12;
강원대학교
13
레퍼런스 복사하기
Copying Object References
Rectangle box =
new Rectangle(5, 10, 20, 30);
Rectangle box2 = box;
box2.translate(15, 25);
강원대학교
14
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
import java.util.*;
public class ReverseList
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
int [] list;
// 배열을 가리킬 참조변수 선언
list = new int[10];
// 배열 인스턴스 구성
System.out.print("Enter 10 integers: ");
// list[0], list[1],..,list[9]로 값 읽기
for (int i= 0; i < 10; i++)
list[i] = input.nextInt();
System.out.print("List in reverse : ");
// list[9], list[8], ... , list[0]에 저장된 값 출력
for (int i= 9; i >= 0; i--)
System.out.print(list[i] + " ");
System.out.println();
}
}
- 15 -
list 배열
- 16 -
프로그램 설명
•
•
for (int i= 0; i < 10; i++)
list[i] = input.nextInt();
•
- 17 -
프로그램 설명
•
•
for (int i= 9; i >= 0; i--)
System.out.print(list[i] + " ");
배열 항목들을 역순인 list[9], list[8], …, list[0]으로 출력한
다.
- 18 -
배열 간편 구성 및 초기화
문자 배열을 선언하고 초기화한다.
char letters[] = {'a', 'b', 'c'};
new 연산자를 사용하지 않는다.
이 letters의 선언과 초기화는 다음과 동일하다.
char letters[] ;
letters = new char[3];
letters[0] = 'a';
letters[1] = 'b';
letters[2] = 'c';
- 19 -
1.
2.
3.
4.
5.
int [] a = {5, 4, 3, 2, 1};
int [] b = new int[5];
// 0으로 초기화
b = a;
a[0] = 100;
System.out.println(“ a[0] is ” + a[0]+ “ and b[0] is ” +b[0]);
출력:
a[0] is 100 and b[0] is 100
- 20 -
•
•
1행: int a = {5,4,3,2,1};
2행: int b = new int[5];
- 21 -
•
3행: b = a
- 22 -
•
4행: B[0] = 100;
- 23 -
배열 비교
int[] a = {5,4,3,2,1};
int[] b = {5,4,3,2,1};
int[] c = a;
a == b 은 거짓(false)이다.
a == c는 참이다.
- 24 -
메소드를 호출할 때 참조변수를
인자로 줄 수 있다.
인자가 메소드의 매개변수로 복사된다.
①
public static void changeMe(int[] data)
{
data[0] = 200;
data[1] = 400;
}
x now has values 200 400 6 8
public static void main(String [] args)
{
int x[] = {2, 4, 6, 8};
changeMe(x);
System.out.print(“x now has values ”+ x[0] + “ ” + x[1] + “ ” +
x[2] + “ ” + x[3]);
}
- 25 -
②
public static void swap (int[] x, int i, int j)
{
// x[i]와 x[j]를 교환한다.
int temp = x[i];
x[i] = x[j];
x[j] = temp;
}
Main 메소드:
int [] list = {1, 3, 5, 7, 9};
swap(list, 2, 4);
// list[2]와 list[4]를 교환해라.
Before: 1 3 5 7 9
After: 1 3 9 7 5
- 26 -
③ 삽입 정렬 (Insertion Sort)
정렬된 리스트내의 올바른 위치로 숫자 삽입
- 27 -
void insert(int[] x, int i)
•
•
•
x[0], x[1], ..., x[i-1] 이 이미 정렬된 상태에서 이 메소드를 호출함
X[i]를 적절한 위치로 이동시켜 x[0], x[1], ..., x[i] 가 정될되도록 함
필요한 경우 일부가 오른쪽으로 위치 이동(shift)하게 됨
public static void insert (int[] x, int i)
int temp = x[i];
int j = i - 1;
while ( j >= 0 && temp < x[j]) {
x[j + 1] = x[j];
// 오른쪽으로 이동
j--;
}
x[j + 1] = temp;
// 올바른 위치에 temp(x[i])를 배치
}
- 28 -
삽입 정렬 (Insertion Sort)
•
n개의 요소가 있는 배열을 정렬하기 위하여, 삽입 정렬은
insert(...) 메소드를 n-1번 호출한다.
- 29 -
// 정렬된 값 x[0], x[1]...x[i-1] 사이의 적절한 위치에 x[i]를 배치
public static void insert (int[] x, int i)
int temp = x[i];
// 값 저장
int j = i - 1;
while ( j >= 0 && temp < x[j]) {
// temp를 배치해야 할 곳 결정
x[j + 1] = x[j];
// 오른쪽으로 위치 이동
j--;
}
x[j + 1] = temp;
//올바른 위치에 temp(x[i])를 배치
}
// x 배열에 저장된 int 데이터 n개를 정렬
public static void insertionSort(int[] x, int n)
for (int i = 1; i < n; i++)
insert(x, i);
}
- 30 -
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int []numbers = new int[1000]; //array can hold up to 1000 integers
int size;
// number of integers that are actually stored
System.out.print("Enter the number of data: ");
size = input.nextInt();
System.out.print("Enter " + size + " integers: ");
//Read the data
for (int i = 0; i < size; i++)
numbers[i] = input.nextInt();
System.out.println();
insertionsort(numbers,size);
System.out.print("Sorted: ");
for (int i = 0; i < size; i++)
System.out.print(numbers[i]+ " ");
System.out.println();
}
31
•
크기가 n 인 데이터 집합에 대한 삽입 정렬은 최대 ½(n2 – n)
의 비교를 수행한다.
•
만약 데이터가 이미 정렬되어 있다면 삽입 정렬은 n – 1의
비교만을 하게 된다.
- 32 -
선형 탐색 (Linear Search)
•
탐색 - 어떤 값(key)이 배열이 들어 있는지 여부와 들어 있
는 경우 어느 위치에 들어 있는지를 알아내는 문제
•
선형 탐색은 x[0]에서 시작하여 배열 내에 있는 각 항목과
키(key)를 순차적으로 비교한다.
• key == x[0] 인가?
• key == x[1] 인가?
• key == x[2] 인가? 등등.
•
•
만약 키가 x[i]와 일치하면, 탐색을 종료하고 i를 반환한다.
키를 배열에서 찾지 못하면 -1을 반환
- 33 -
선형 탐색
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
public static int search(int[] x, int n, int key)
{
// 배열 x에서 키와 같은 숫자의 위치를 반환
// 만약 키를 찾지 못하면 -1을 반환
// 배열 x는 부분적으로만 채워짐. n은 x에 있는 데이터의 개수
for ( int i = 0; i < n; i++)
if (key == x[i])
return i;
return -1;
// 키를 발견함
// 인덱스를 반환
// 키를 찾지 못함
}
- 34 -
이진 탐색 (Binary Search)
• 선형 탐색보다 빨리, 더 적은 연산으로 탐색 수행
• 배열이 미리 정렬되어 있어야 한다.
• <예>
• 아래 정렬된 배열에서 키 27을 탐색
[3 5 6 9 11 23 25 26 27 29 33 35 36 37 39 42 45 46 48 58 62 67 70]
- 35 -
- 36 -
단 세 번의 비교로 탐색 완료!
- 37 -
1.
// x는 n개의 정수가 정렬된 배열이다.
2. static int search(int[] x , int n, int key) {
3.
int lo = 0;
// 배열의 최소 인덱스
4.
int hi = n-1;
// 최대 인덱스
5.
int mid;
// 중앙 인덱스
6.
while (hi >= lo) {
7.
mid = (hi + lo) / 2;
// 중앙 인덱스 계산
8.
if (key == x[mid])
9.
return mid;
//키 발견 -- 종료
10.
if (key < x[mid])
11.
hi = mid - 1;
//x[mid]에서 x[hi]까지 제외
12.
else
13.
lo = mid + 1;
// x[lo]에서 x[mid]까지 제외
14.
}
15.
return -1;
// 키를 발견하지 못함
16. }
- 38 -
이진 탐색 동작
key = 27; 밝게 강조된 블록은 탐색으로부터 제외된다.
반복 1
lo = 0; hi = 22; mid = 11
반복 2
lo = 0; hi = 10; mid = 5
반복 3
lo= 6; hi = 10; mid = 8
hi 수정 : hi = mid – 1
lo 수정 : lo = mid + 1
키의 인덱스 값 8을
반환
- 39 -
.
이진 탐색
n 개 항목의 리스트에 대하여 선형 탐색은 평균적으로 n/2 위치를 검사한다.
이진 탐색은 약 log2 n – 1 위치들만 검사한다.
n
210
215
220
225
n/2 (선형 탐색)
=1024
=32768
=1048576
=33554432
512
16384
524288
16777216
log2n –1 (이진 탐색)
9
14
19
24
- 40 -
배열을 가리키는 참조변수를 반환하는 메소드
int[] arr
•arr이 int 배열을 가리키는 참조변수이다!
int[] getArray()
•getArray()가 int 배열을 가리키는 참조변수이다!
•getArray()의 반환값이 int 배열을 가리키는 참조변수이다!
•getArray()는 int 배열을 가리키는 참조변수를 반환한다!
41
import java.util.Arrays;
public class ArrayTest {
public static void main(String[] args) {
int[] anArray;
anArray = getArray();
System.out.println(Arrays.toString(anArray));
}
static int[] getArray() {
int[] a = {1, 2, 3};
return a;
}
}
42
2차원 배열
(two-dimensional array)
행(row)과 열(column)
- 43 -
2차원 배열
B는 2 × 2 배열이고, C는 3 × 2 배열이다.
A[i][j]은 i행, j열의 셀
- 44 -
2차원 배열
- 45 -
2차원 배열 선언과 구성
int[][] table;
// 참조변수 선언
table = new int[2][3];
// 배열 인스턴스를 구성하고
// 참조변수에 배열 주소를 저장
int[][] table = new int[2][3];
- 46 -
2차원 배열 처리
int A[][] = new int[3][4];
// 3×4 배열의 선언과 구성
for (int row = 0; row < 3; row++)
// 각 행에 대하여
for (int col = 0; col < 4; col++)
// 각 열에 대하여
A[row] [col] = row * col;
row = 0
col = 0
col = 1
col = 2
col = 3
A[0][0] = 0
A[0][1] = 0
A[0][2] = 0
A[0][3] = 0
row = 1
col = 0
col = 1
col = 2
col = 3
col = 0
col = 1
col = 2
col = 3
A[1][0]
A[1][1]
A[1][2]
A[1][3]
A[2][0]
A[2][1]
A[2][2]
A[2][3]
row = 2
=0
=1
=2
=3
=0
=2
=4
=6
0
0
0
0
1
2
0 0
2 3
4 6
- 47 -
배열 간편 구성 및 초기화
int[][] table = { {2, 4, 6}, {8, 10, 12} };
- 48 -
2차원 배열 처리
2-차원 배열로 데이터 읽어 들이는 예:
Scanner input = new Scanner(System.in);
int [][] a = new int[5][4];
for (int row = 0; row < 5; row++)
for (int col= 0; col < 4; col++)
a[row][col] = input.nextInt();
- 49 -
2차원 배열 처리
행 단위로 저장된 값 출력 형식:
for ( int row = 0; row < 5; row++) {
for (int col = 0; col < 4; col++)
System.out.print (a[row][col] + “ “);
System.out.println();
}
//
//
//
//
각 행에 대하여
각 열에 대하여
열의 값 출력
new line
- 50 -
3차원 배열
int[][][] threeD;
threeD = new int[3][4][5];
for (int i = 0; i < 3; i++)
for (int j = 0; j < 4; j++)
for (int k = 0; k < 5; k++)
threeD[i][j][k] = i * j * k;
- 51 -
2차원 배열 처리 예
•
분할표(contingency table)는 두 변수 사이의 관계를 분석하기 위한 보
조 도구로서 종종 사용되는 2차원 표이다.
•
예를 들어, 한 연구원은 1,000명을 조사하여 다음과 같은 결과를 얻었
다. 이 표는 성별과 음악 선호도 사이의 관련성을 보여준다.
Males
123
Heavy
Metal
145
Females
138
112
50
27
93
75
10
13
518
Total
261
257
83
61
109
146
28
55
1000
Rock
Folk
Jazz
R& B
Pop
Country
Other
Total
33
34
16
71
18
42
482
- 52 -
문제
다음을 실행하는 프로그램을 작성하여라.
분할표의 행(row)과 열(column)의 개수를 사용자에게 묻는다.
행 단위로 데이터를 읽는다.
행의 합, 열의 합, 총 합계와 데이터를 표 형식으로 출력한다.
샘플 출력
1
7
8
3
9
12
6
|
8
|
14 |
10
24
34
- 53 -
해법
다음과 같은 세 가지의 메소드를 사용한다.
readData (...)는 사용자에 의해 제공되는 데이터를 2차원 배열에
저장한다. 데이터는 행 단위로 입력된다.
getTotals(...)는 행의 합과 열의 합을 계산한다.
display(...)는 행, 열, 총 합계의 표를 출력한다.
- 54 -
import java.util.*;
public class ContingencyTable {
public static void readData( int[][] table, int numRows,
int numCols) {
// 행 단위로 표의 데이터를 읽는다.
// table은 row 개의 행과 col 개의 열을 가진다.
System.out.println("Enter data, row by row: ");
Scanner input = new Scanner(System.in);
// 행 단위로 데이터를 읽는다.
for (int row = 0; row < numRows; row++)
for (int col = 0; col < numCols; col++)
table[row][col] = input.nextInt();
}
- 55 -
public static void getTotals(int[][]table, int numRows, int numCols,
int[] rowSums, int [] colSums) {
// 행의 합과 열의 합을 계산한다.
// 행의 합을 계산한다.
for (int row = 0; row < numRows; row++)
for (int col = 0; col < numCols; col++)
rowSums[row] += table[row][col];
for (int col = 0; col < numCols; col++)
for (int row = 0; row < numRows; row++)
colSums[col] += table[row][col];
}
- 56 -
public static void display(int table[][], int numRows, int numCols,
int[] rowSums, int[] colSums) {
// 분할표를 출력한다.
// 열과 행의 합과 총 합계를 출력한다.
System.out.println();
System.out.println();
System.out.println("Data including row and column totals: ");
System.out.println();
// 행 단위로 표를 출력한다.
// 행을 출력한 후에 행의 합을 출력한다.
for(int row = 0; row < numRows; row++)
{
for (int col = 0; col < numCols; col++)
System.out.print(" " + table[row][col] + "\t");
System.out.println("| " + rowSums[row]);
}
다음 쪽에 계속 ~
- 57 -
System.out.println();
int grandTotal = 0;
// 열의 합으로부터 총 합계를 계산한다.
// 열의 합을 출력하고 총 합계를 출력한다.
for (int col = 0; col < numCols; col++)
{
grandTotal += colSums[col];
System.out.print(" " + colSums[col] + "\t");
}
System.out.println("| "+grandTotal);
}
- 58 -
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int rows, cols;
int[][] table;
int[] rowSums;
int colSums[];
System.out.print("Number of rows: " );
rows = input.nextInt();
System.out.print("Number of columns: ");
cols= input.nextInt();
table = new int[rows][cols];
rowSums = new int[rows];
colSums = new int[cols];
readData(table, rows, cols);
getTotals(table, rows, cols, rowSums, colSums);
display(table, rows, cols, rowSums,colSums);
}
}
- 59 -
실행
Number of rows: 2
Number of columns: 8
Enter data, row by row:
123 145 33 34 16 71 18 42 138 112 50 27 93 75 10 13
Data including row and column totals:
123
138
145
112
33
50
34
27
16
93
71
75
261
257
83
61
109
146
18
10
28
42
13
55
| 482
| 518
| 1000
- 60 -
인덱스 범위 초과 오류
for (int i = 0; i <= x.length; i++)
X
for (int i = 0; i < x.length; i++)
○
- 61 -
끝
62