目的
Java 的原生基本資料型態共有 8 個,比如 int、short….。當我們想要建立一個叫 Student 的資料型態,裏面有名字、英文成績、數學成績,此時就必需把這三項型態組合成一個自訂的資料型態。
語法
自訂的資料型態在 C 語言使用 struct 指令,在 Java 裏直接改成 class。請注意如下 class Student 是寫在 public class Test 之外,也就是外部類別。
要產生一個新的 Student,使用 new 關鍵字。這跟 C 語言調用 malloc() 函數一樣,都是跟系統要求某一區塊的記憶體。產生出來的 s1 稱為物件 (Object)。要存取 s1 裏的 name、eng 就直接在 s1後面加上「.」。 「.」 就是「的」, 比如 s1.name 即「s1 的 name」。
public class Test {
public static void main(String[] args){
Student s1=new Student();
s1.name="Thomas";
s1.eng=100;
s1.math=80;
}
}
class Student{
String name;
int eng, math;
}
上面的代碼可以簡略下一個定論 : 什麼是類別 (class) ? 類別就是一個自訂的資料型態。
預設值
產生出來的 s1,裏面的變數會被系統自動初始化, String 初始化為 null,int 初始化為 0,小數初始化為 0.0。
public class Test {
public static void main(String[] args){
Student s1=new Student();
System.out.printf("namd : %s, eng : %d, math : %d\n", s1.name, s1.eng, s1.math);
}
}
class Student{
String name;
int eng, math;
}
結果 :
namd : null, eng : 0, math : 0
單向連結
陣列的限制
使用陣列時,必需先宣告,如
int[] array=new int[10];
a 是一個長度為10 個元素的陣列,一經宣告長度就不能改變。重點在於一開始我們怎麼知道是要宣告為 10 或 100 呢?
比如要記錄每個客人消費的金額,打從一開門,到底是要宣告有幾個客人? 因為無法預測,所以無法定長度。
解決方案
上述的問題很明顯使用陣列是無法解決,所以必需另想辦法。下圖即是資料結構課程裏頂頂有名的單向連結。先產生一個 root 及 index,並產生一個節點 @f1。
當需要記錄某數字比如50,就將 50 放入 @f1中,然後再產生一個節點 @f2,此 @f2 記錄在 @f1 的 next 變數中。當要再次記錄另一個數字,就放入最後的節點,然後再產生一個新的節點 stand by。
如此就可以無限的擴充長度,只要記憶體不要爆掉就好。就算記憶體爆了,還是可以寫個網路連結的方法,將別台電腦的記憶體納入自已來使用。

程式代碼
上述的每一個節點都有二個值,一個是記錄數字用的,另一個是記錄下一個節點。所以節點的自訂資料格式為
class Node{
int d;
Node next;
}
上面的 Node next,是說 class 裏有一個變數,而這個變數是指向一個新的 Node ,完整代碼如下。
public class SingleLink {
public static void main(String[] args){
Node root=new Node();
Node index=root;
Scanner in=new Scanner(System.in);
int x=0;
while(true){
System.out.print("請輸入數字(-1離開) : ");
x=in.nextInt();
if(x==-1)break;
index.d=x;
index.next=new Node();
index=index.next;
}
index=root;
while(index.next!=null){
System.out.printf("%d ", index.d);
index=index.next;
}
System.out.println();
}
}
class Node{
int d;
Node next;
}
結果 :
請輸入數字(-1離開) : 10
請輸入數字(-1離開) : 50
請輸入數字(-1離開) : 60
請輸入數字(-1離開) : 70
請輸入數字(-1離開) : 80
請輸入數字(-1離開) : 90
請輸入數字(-1離開) : -1
10 50 60 70 80 90
雙向連結
單向連結的缺點
前一章所提及的單向連結可以無限的擴充長度,只要記憶體不要爆掉就好。但有一個缺失就是無法反向列印。
解決方案
單向連結無法反向列印,其實是可以用其他演算法解決。但這演算法實在是太耗費時間,所以才會有如下的結構。下面每個節點又多一個記錄前一個節點的變數 prev,如果就可以正反向列印。

代碼
public class DoubleLink {
public static void main(String[] args){
Node root=new Node();
Node index=root;
Scanner in=new Scanner(System.in);
int x=0;
while(true){
System.out.print("請輸入數字(-1離開) : ");
x=in.nextInt();
if(x==-1)break;
index.d=x;
index.next=new Node();
index.next.prev=index;
index=index.next;
}
//正向列印
index=root;
System.out.println("正向列印......");
while(index.next!=null){
System.out.printf("%d ", index.d);
index=index.next;
}
System.out.println();
//反向列印
index=root;
while(index.next!=null)index=index.next;
System.out.println("反向列印......");
while(index.prev!=null){
System.out.printf("%d ", index.prev.d);
index=index.prev;
}
System.out.println();
}
}
class Node{
Node prev;
int d;
Node next;
}
結果 :
請輸入數字(-1離開) : 10
請輸入數字(-1離開) : 20
請輸入數字(-1離開) : 30
請輸入數字(-1離開) : 40
請輸入數字(-1離開) : 50
請輸入數字(-1離開) : -1
正向列印......
10 20 30 40 50
反向列印......
50 40 30 20 10
二元樹排序法
規則
二元樹排序(Binary Sort)又有人稱為黑紅樹,它是所有高科技的開端,沒有這個演算法就不會有現今這個世界。其規則如下
1. 左邊小, 右邊大 2. 左中右, 中間取值
架構圖

程式架構
下面的代碼依序執行如下動作
1. 產生n 個元素的陣列
2. 將亂數填入陣列中
3. 將陣列列印出來
4. 建立二元樹
5. 排序
6. 列印排序後的陣印
package binarytree;
public class BinaryTree {
static int[]array;
static int index=0;
public static void main(String[] args) {
//產生陣列並填入亂數
int n=10;
array=new int[n];
for (int i=0;i<array.length;i++){
array[i]=(int)(Math.random()*10000);
}
//列印未排序的陣列
printData(array);
//建立二元樹
Node root=null;
for (int i=0;i<array.length;i++){
root=bt(root, array[i]);
}
//排序
sort(root);
//列印排完序後的陣列
printData(array);
}
public static void printData(int[] array){
//todo
}
//bt : buildTree的縮寫
public static Node bt(Node node, int value){
//todo
}
public static void sort(Node node){
//todo
}
}
//節點資料結構
class Node{
Node left;
Node right;
int value;
public Node(int value){
this.value=value;
}
}
完整代碼
package binarytree;
public class BinaryTree {
static int[]array;
static int index=0;
public static void main(String[] args) {
/*
1. n=10;
2. 產生陣列 array
3. 填入亂數
4. 列印
5. 建立二元樹
6. 排序
7. 列印
*/
int n=10;
array=new int[n];
for (int i=0;i<array.length;i++){
array[i]=(int)(Math.random()*10000);
}
printData(array);
Node root=null;
for (int i=0;i<array.length;i++){
root=bt(root, array[i]);
}
sort(root);
printData(array);
}
public static void printData(int[] array){
for (int i=0;i<array.length;i++){
System.out.printf("%d ", array[i]);
}
System.out.println();
}
public static Node bt(Node node, int value){
//進入點沒東西, 就產生節點
if (node==null)node=new Node(value);
//否則就判斷是往左邊走, 或往右邊走
else if (value<node.value)node.left=bt(node.left, value);
else node.right=bt(node.right, value);
return node;
}
public static void sort(Node node){
//左中右, 中間取值
//底下為往左邊走
if (node.left!=null)sort(node.left);
//中間取值
array[index++]=node.value;
//接下來, 往右邊走
if (node.right!=null)sort(node.right);
}
}
class Node{
Node left;
Node right;
int value;
public Node(int value){
this.value=value;
}
}
結果 :
29 154 252 349 411 447 462 543 734 982
