8 grundlegende Sortieralgorithmen


Einleitung: Im Leben kommen wir nicht ohne Sortieren aus. Im Sportunterricht werden die Schüler beispielsweise nach ihrer Körpergröße sortiert, oder wenn Schulen Schüler aufnehmen, werden sie nach ihren Noten von hoch nach niedrig usw. sortiert; und der Sortieralgorithmus ist auch ein häufig gefragter Algorithmus in Interviews (im Folgenden). Die Sortierung erfolgt standardmäßig von klein nach groß.)...


Klassifizierung des Sortieralgorithmus

Eingeteilt nach zeitlicher Komplexität:

  • Die Zeitkomplexität beträgt O(n^2)
    • Blasensortierung
    • Auswahl sortieren
    • direkte Einfügungssortierung
    • Hill-Sortierung (die besondere Zeitkomplexität liegt zwischen O(nlogn) und O(n^2))
  • Die Zeitkomplexität beträgt O(nlogn)
    • Schnelle Sorte
    • Heap-Sortierung
    • Zusammenführen, sortieren
  • Die Zeitkomplexität ist lineare Ordnung O(n)
    • Eimersortierung
    • Radix-Sortierung

Klassifizierung nach Stabilität:

稳定性:对于序列a中值相等的元素a[i]=a[j],i<j;排序以后的序列中a[i]、a[j]的前后位置不变则为稳定,反之则为不稳定。

  • Stabile Sortierung: Direkteinfügungssortierung, Halbauswahlsortierung, Blasensortierung, Zusammenführungssortierung, Basissortierung
  • Instabile Sortierung: Heap-Sortierung, Schnellsortierung, Hill-Sortierung, Direktauswahl-Sortierung

Blasensortierung

Vergleichen Sie Paare benachbarter Elemente in der Sequenz und verschieben Sie den Maximalwert zwischen zwei benachbarten Elementen schrittweise nach hinten, bis der Maximalwert ganz nach rechts verschoben wird und der zweitgrößte Wert ganz nach rechts verschoben wird ..., wie ein Risiko Wie Blasen Lassen Sie die größere Blase nach oben schweben.

Fügen Sie hier eine Bildbeschreibung ein

//todo 1.冒泡排序
    public static void maopao(int[] arr){
    
    
        int len=arr.length;
        for (int i=1;i<len;i++){
    
    
            boolean is_sort=true;  //假设有序
            for (int j=0;j<len-i;j++){
    
    
                if (arr[j]>arr[j+1]){
    
     //交换相邻元素
                    arr[j]=arr[j]^arr[j+1];
                    arr[j+1]=arr[j]^arr[j+1];
                    arr[j]=arr[j]^arr[j+1];
                    is_sort=false;
                }
            }
            if (is_sort){
    
     //如果这一轮没有交换说明已经有序了,直接退出
                break;
            }
        }
    }

Auswahl sortieren

Idee: Wählen Sie in jeder Runde den Index des kleinsten Elements aus und tauschen Sie dann direkt den Index des kleinsten Elements mit dem linken Element aus. Der größte Vorteil dieser Sortierung besteht darin, dass ein mehrfacher Austausch ähnlich der Blasensortierung entfällt.

//todo 2.选择排序
    public static void change(int[] arr){
    
    
        int len=arr.length;
        for (int i=0;i<len;i++){
    
    
            int minIndex=i; //选定最小元素索引
            for (int j=i+1;j<len;j++){
    
    
                if (arr[j]<arr[minIndex])
                    minIndex=j;
            }
            if (minIndex != i){
    
     
                arr[minIndex]=arr[minIndex]^arr[i];
                arr[i]=arr[minIndex]^arr[i];
                arr[minIndex]=arr[minIndex]^arr[i];
            }
        }
    }

direkte Einfügungssortierung

Idee: Behalten Sie einen geordneten Bereich bei und fügen Sie die Elemente im Array nacheinander an den entsprechenden Positionen im geordneten Bereich ein, bis alle Elemente des Arrays geordnet sind.
Fügen Sie hier eine Bildbeschreibung ein

//todo 3.直接插入排序
    public  static void insert_sort(int[] arr){
    
    
        int len=arr.length;
        for (int i=1;i<len;i++){
    
    
            int j=i-1;
            int tmp=arr[i]; //将当前元素拷贝,用以与之前元素比较插入
            while (j>=0 && tmp<arr[j]){
    
    
                arr[j+1]=arr[j]; //将较大元素往后移动,以备当前元素插入
                j--; //逐步向之前元素进行比较
            }
            arr[j+1]=tmp;
        }
    }

Schnelle Sorte

Idee: Wählen Sie in jeder Runde einen Benchmark-Element-Pivot aus und verschieben Sie andere Elemente, die größer als dieser sind, nach rechts vom Pivot und verschieben Sie die kleineren Elemente nach links, wodurch das Array in zwei Teile geteilt wird. Sortieren Sie dann die beiden Teile rekursiv – - -Teile und herrsche.

//todo 4.快速排序
    public static void quick_sort(int[] arr,int left,int right){
    
    
        if (left>right)
            return;
        int i=left;
        int j=right;
        int pivot=arr[left];
        while (i<j){
    
    
            while (i<j && arr[j]>pivot)
                j--;
            while (i<j && arr[i]<=pivot)
                i++;
            if (i<j){
    
    
                arr[i]=arr[i]^arr[j];
                arr[j]=arr[i]^arr[j];
                arr[i]=arr[i]^arr[j];
            }
        }
        //将基准元素与重合元素交换
        arr[left]=arr[i];
        arr[i]=pivot;
        quick_sort(arr,left,i-1); //将左边部分递归排序
        quick_sort(arr,i+1,right); //将右边部分递归排序
    }

Zusammenführen, sortieren

Idee: Die Zusammenführungssortierung besteht darin, die Sequenz rekursiv in kurze Sequenzen (Gruppen) zu unterteilen. Der rekursive Ausgang besteht darin, dass die kurze Sequenz nur 1 Element (als direkt geordnet betrachtet) oder 2 Sequenzen (1 Vergleich und Austausch) hat und dann jeweils geordnet wird Segment ist Sequenzen werden zu einer langen geordneten Sequenz zusammengeführt (Zusammenführung) und kontinuierlich zusammengeführt, bis alle ursprünglichen Sequenzen sortiert sind.
Fügen Sie hier eine Bildbeschreibung ein

//todo 5.归并排序
    //5.1 数组分组
    public static void split_arr(int[] arr,int left,int right){
    
    
        if (left < right){
    
    
            int middle=left+(right-left)/2; //防止(right+left)/2 数据溢出
            //左边分组
            split_arr(arr,left,middle);
            //右边分组
            split_arr(arr,middle+1,right);
            //分组合并排序
            merge_arr_sort(arr,left,middle,right);
        }
    }
    //5.2 数组合并排序
    public static void merge_arr_sort(int[] arr,int left,int middle,int right){
    
    
        int[] tmp=new int[right-left+1]; //存储合并的数组
        int i=left;
        int j=middle+1;
        int t=0;
        while (i<=middle && j<=right){
    
    
            if (arr[i]<arr[j]){
    
    
                tmp[t++]=arr[i++];
            }else tmp[t++]=arr[j++];
        }
        while (i<=middle) //当左边部分还有剩余元素(剩余元素因为之前的排序已经有序)时直接插入临时数组
            tmp[t++]=arr[i++];
        while (j<=right) //当右边部分还有剩余元素时直接插入临时数组
            tmp[t++]=arr[j++];
        //将合并的数组拷贝到原数组中
        System.arraycopy(tmp,0,arr,left,tmp.length);
    }

Hill-Sorte

Idee: Wenn die meisten Elemente im Array in Ordnung sind, ist der Arbeitsaufwand für die Einfügungssortierung relativ gering und die Elemente im Array müssen nicht häufig verglichen und ausgetauscht werden.
Fügen Sie hier eine Bildbeschreibung ein

//todo 6.希尔排序
    public static void shell_sort(int[] arr){
    
    
        int len=arr.length;
        for (int d=len/2;d>0;d/=2){
    
     //d:增量
            for (int i=d;i<len;i++){
    
    
                int j=i-d;
                int tmp=arr[i];
                while (j>=0 && tmp<arr[j]){
    
    
                    arr[j+d]=arr[j];
                    j -= d;
                }
                arr[j+d]=tmp;
            }
        }
    }

Eimersortierung

Idee: Teilen Sie das Array in eine begrenzte Anzahl von Buckets auf. Jeder Bucket wird dann einzeln sortiert (es ist möglich, andere Sortieralgorithmen zu verwenden oder die Bucket-Sortierung weiterhin auf rekursive Weise zu verwenden), und schließlich werden die Datensätze in jedem Bucket aufgelistet, um sich die geordnete Reihenfolge zu merken.

//todo 7.桶排序
    public static int[] bucket_sort(int[] arr){
    
    
        int len=arr.length;
        //1.求极值
        int max=arr[0];
        int min=arr[0];
        for (int i=1;i<len;i++){
    
    
            if (arr[i]<min)
                min=arr[i];
            if (arr[i]>max)
                max=arr[i];
        }
        int d=max-min;
        //2.对桶进行初始化
        ArrayList<LinkedList<Integer>> buckets = new ArrayList<>(len);
        for (int i=0;i<len;i++){
    
    
            buckets.add(new LinkedList<>());
        }
        //3.对数组中元素存放到对应桶中(将桶中元素映射到0~len-1的索引中)
        for (int x:arr){
    
    
            int index=(int)((x-min)/d*(len-1));
            buckets.get(index).add(x);
        }
        //4将各个桶中所有元素排序
        for (int i=0;i<len;i++){
    
    
            Collections.sort(buckets.get(i));
        }
        //5输出各元素
        int[] result = new int[len];
        int t=0;
        for (int i=0;i<len;i++){
    
    
            for (int j=0;j<buckets.get(i).size();j++)
                result[t++]=buckets.get(i).get(j);
        }
        return result;
    }

Heap-Sortierung

Der Heap ist eine Datenstruktur, die als vollständiger Binärbaum bezeichnet wird und in einen großen Root-Heap und einen kleinen Root-Heap unterteilt werden kann. Die Heap-Sortierung ist ein Programmalgorithmus, der auf dieser Struktur basiert.
Fügen Sie hier eine Bildbeschreibung ein

//todo 8.堆排序
    /*
    * @param arr 要维护的数组
    * @param parentIndex 要维护的节点
    * @param len 要维护的数组长度
    * */
    public static void heapify(int[] arr,int parentIndex,int len){
    
    
        //计算左右子节点
        int leftChildren = 2*parentIndex+1;
        int rightChildren = leftChildren+1;
        //求最大节点的索引
        int largest = parentIndex;
        if (leftChildren<len && arr[leftChildren]>arr[largest])
            largest = leftChildren;
        if (rightChildren<len && arr[rightChildren]>arr[largest])
            largest = rightChildren;
        if (largest != parentIndex){
    
    
            arr[largest]=arr[largest]^arr[parentIndex];
            arr[parentIndex]=arr[largest]^arr[parentIndex];
            arr[largest]=arr[largest]^arr[parentIndex];
            //维护parentIndex节点
            heapify(arr,largest,len);
        }
    }
    //创建最大堆
    public static void heap_sort(int[] arr){
    
    
        int len=arr.length;
        for (int i=len/2-1;i>=0;i--){
    
    
        //最后一个节点索引为len-1,其对应的父节点带入(n-1)/2即得:len/2-1
            //从最后一个父节点开始维护最大堆性质
            heapify(arr,i,len);
        }
        //选择最大元素进行交换
        for (int i=len-1;i>0;i--){
    
    
            arr[i]=arr[i]^arr[0];
            arr[0]=arr[i]^arr[0];
            arr[i]=arr[i]^arr[0];
            //将互换以后的堆顶维护性质
            heapify(arr,0,i);
        }
    }

Interview 1:
Es gibt eine Datei. Jede Zeile der Datei enthält Buchinformationsdaten. Sie ist durch Kommas (,) in 4 Teile unterteilt. Das Format ist wie folgt:
id,category,words,updatetime
id stellt die Buch-ID dar, langer Typ, und die ID ist nicht wiederholt;
Kategorie stellt die Klassifizierung des Buches dar, Typ int. Bitte beachten Sie, dass die Klassifizierung aller Daten nur wenige
Wörter umfasst, was die Anzahl der Wörter im Buch darstellt, und dass der Typ int
updatetime die Aktualisierungszeit des Buches darstellt . Das Format ist 2020-02-01 23:00:00

4
66,20002,25919,2020-02-16 17:35:00
63,20004,9914,2020-02-16 17:35:00
60,20001,1982,2020-02-16 17:35:00
68,20004,1693,2020-02-16 17:35:00

Bitte schreiben Sie ein Programm, um die Dateidaten zu sortieren und dann die ID auszugeben. Die Sortierpriorität ist: Kategorie>Updatezeit>Wörter>ID, Sortierung in aufsteigender Reihenfolge.

public class Demo3 {
    
    
   
        public static void main(String[] args) throws Exception {
    
    
            //时间转换格式
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            ArrayList<Book> books = new ArrayList<>();
            //获取文件数据流
            File file = new File("G:/t1.txt");
            try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) {
    
    
                List<String> list =bufferedReader.lines()  //bufferedreader读取文件数据
                        .filter(e -> e.length() > 4)
                        .collect(Collectors.toList());
                for (String e:list){
    
    
                    String[] fields = e.split(",");
                    books.add(new Book(Long.parseLong(fields[0]),Integer.parseInt(fields[1]),
                            Integer.parseInt(fields[2]),dateFormat.parse(fields[3]).getTime()));
                }
                books.sort(new Comparator<Book>() {
    
    
                    @Override
                    public int compare(Book o1, Book o2) {
    
    
                        if (o1.getCategory()!=o2.getCategory()){
    
    
                            return o1.getCategory()-o2.getCategory();
                        }else if (o1.getUpdatetime()!= o2.getUpdatetime()){
    
    
                            return (int) (o1.getUpdatetime()-o2.getUpdatetime());
                        }else if (o1.getWords()!=o2.getWords()){
    
    
                            return o1.getWords()-o2.getWords();
                        }else return (int) (o1.getId()-o2.getId());
                    }
                });
                books.forEach(e->{
    
    
                    System.out.println(e.getId());
                });
                // 结果:60 66 68 63
            }
        }

     static class Book{
    
      //将文件中的数据封装成书籍类
            private long id;
            private int category;
            private int words;
            private long updatetime;
            //todo 省略set、get方法,无参有参方法
     }
}

Interview 2: Zwei geordnete Arrays zu einem neuen geordneten Array zusammenführen

public class test2 {
    
    

    public static void main(String[] args) {
    
    
      // 合并两个有序数组,成为一个新的有序数组
        int[] arr1 = {
    
    10,18,22,40,56};
        int[] arr2 = {
    
    7,12,32,50,54};
        System.out.println("合并以后的数组为:"+Arrays.toString(merge_arr(arr1,arr2)));
    }

    //参考的归并排序中的归并操作
    private static int[] merge_arr(int[] arr1, int[] arr2) {
    
    
        //创建临时数组用以存储合并两个数组的元素
        int[] tmp = new int[arr1.length + arr2.length];
        int t=0;
        int i=0,j=0;
        while (i<arr1.length && j<arr2.length){
    
    
            if (arr1[i]<arr2[j]){
    
    
                tmp[t++]=arr1[i++];
            }else tmp[t++]=arr2[j++];
        }
        while (i<arr1.length)
            tmp[t++]=arr1[i++];
        while (j<arr2.length)
            tmp[t++]=arr2[j++];
        return tmp;
    }
}

Interview 3: In einem Array von N ganzen Zahlen gibt es mehrere ungerade und gerade Zahlen. Entwerfen Sie einen Sortieralgorithmus, sodass alle ungeraden Zahlen links stehen.

	public static void get_result2(int[] arr){
    
    
        //设置两个指针p1,p2指向头和尾,直到p1为偶数,p2为奇数时交换两指针的值(参考了快速排序)
        int p1=0,p2=arr.length-1;
        while (p1<p2){
    
    
            while ((arr[p1]&1)!=0)
                p1++;
            while ((arr[p2]&1)==0)
                p2--;
            if (p1<p2){
    
    
                arr[p1]=arr[p1]^arr[p2];
                arr[p2]=arr[p1]^arr[p2];
                arr[p1]=arr[p1]^arr[p2];
            }
        }
    }

Interview: Erstellen, Löschen, Sortieren, Umkehren und andere Vorgänge verknüpfter Listen

public class test7 {
    
    

    //todo size标记链表长度(节点个数)
    private static int size=0;

    public static void main(String[] args) {
    
    
        //创建链表
        Node head = create_link(5);
        show_link(head);
        System.out.println("获取第2个节点"+get_index(2+1,head));
        System.out.println("向链表第三个位置插入333:");
        insert(3, 333, head);
        show_link(head);
        System.out.println("向链表头部插入0:");
        head = insert(1, 0, head);
        show_link(head);
        System.out.println("向链表尾部插入999:");
        head = insert(size, 999, head);
        show_link(head);
        System.out.println("删除头部节点:");
        head = delete_index(1, head); //删除头部节点
        show_link(head);
        System.out.println("删除尾部节点:");
        head = delete_index(size, head);
        show_link(head);
        System.out.println("删除第三个节点:");
        head = delete_index(3, head);
        show_link(head);
        System.out.println("链表反转后:");
        head = recursion_reverse(head);
        show_link(head);
        System.out.println("排序以后的链表:");
        show_link(maopao_sort(head));
    }

    //todo 向链表中第index个位置插入element元素
    public static Node insert(int index,int element,Node head){
    
    
        if (index<=0 || index>size){
    
    
            throw new IndexOutOfBoundsException("插入位置有误!");
        }
        if (index==1){
    
      //插入头部
            Node current = new Node(element);
            current.next=head;
            head=current;
        }else if (index==size){
    
      //插入尾部
            Node pre_last = get_index(index, head);
            pre_last.next.next=new Node(element);
        }else {
    
      //插入中间部分
            //先获取第index-1的节点
            Node pre_index = get_index(index, head);
            Node current = new Node(element);
            current.next=pre_index.next;
            pre_index.next=current;
        }
        size++;
        return head;
    }

    //TODO 头插法创建链表
    public static Node create_link(int n){
    
    
        size=n;
        Node head=null;
        Scanner scanner = new Scanner(System.in);
        System.out.println("输入链表data:");
        for (int i=0;i<n;i++){
    
    
            if (i==0){
    
    
                head=new Node(scanner.nextInt());
            }else {
    
    
                Node current=new Node(scanner.nextInt());
                current.next=head;
                head=current;
            }
        }
        return head;
    }

    //todo 尾插法创建链表
    public static Node create_link2(int n){
    
    
        size=n;
        Node head=null;
        Node tmp=null;
        Scanner scanner = new Scanner(System.in);
        System.out.println("输入链表data:");
        for (int i = 0; i < n; i++) {
    
    
            if (i==0){
    
    
                head=new Node(scanner.nextInt());
                head.next=null;
                tmp=head;
            }else{
    
    
                Node current = new Node(scanner.nextInt());
                tmp.next=current;
                tmp=current;
                current.next=null;
            }
        }
        return head;
    }

    //todo 展示链表所有节点数据
    public static void show_link(Node head){
    
    
        Node tmp=head;
        System.out.print("链表所有数据:");
        while (tmp!=null){
    
    
            System.out.print(tmp.data+" ");
            tmp=tmp.next;
        }
        System.out.println();
    }

    //todo 获取index-1的节点数据
    public static Node get_index(int index,Node head){
    
    
        Node tmp=head;
        for (int i =1; i < index-1; i++) {
    
    
            tmp=tmp.next;
        }
        return tmp;
    }

    //todo 删除第index个节点
    public static Node delete_index(int index,Node head){
    
    
        if (index<=0 || index>size){
    
    
            throw new IndexOutOfBoundsException("删除位置有误!");
        }
        if (index==1){
    
      //删除头节点
            head= head.next;
        }else if (index==size){
    
     //删除尾结点
            Node pre_index = get_index(index, head);
            pre_index.next=null;
        }else {
    
      //删除中间节点
            Node pre_index = get_index(index, head);
            pre_index.next=pre_index.next.next;
        }
        size--;
        return head;
    }

    //TODO 使用冒泡排序对链表进行排序
    public static Node maopao_sort(Node head){
    
    
        Node new_head=head;
        for (int i=1;i<size;i++){
    
    
            Node pre=null;
            Node current=new_head;
            Node N=current.next;
            for (int j=0;j<size-i;j++){
    
    
                if (current.data>N.data){
    
    
                    current.next=N.next;
                    N.next=current;
                    if (pre==null){
    
    
                        new_head=N;
                    }else{
    
    
                        pre.next=N;
                    }
                    pre=N;
                    N=current.next;
                }else {
    
    
                    pre=current;
                    current=N;
                    N=N.next;
                }
            }
        }
        return new_head;
    }

    //todo 链表反转
    public static Node reverse_link(Node head){
    
    
        Node new_head=null;
        Node tmp=head;
        Node Next=head;
        while (Next!=null){
    
    
           Next=Next.next;
           tmp.next=new_head;
           new_head=tmp;
           tmp=Next;
        }
        return new_head;
    }

    //todo 链表递归反转
    public static Node recursion_reverse(Node head){
    
    
        if (head.next==null)
            return head;
        Node new_head = recursion_reverse(head.next);
        head.next.next=head;
        head.next=null;
        return new_head;
    }

    //链表节点对象
    static class Node{
    
    

        private int data; //数据域
        private Node next; //指针域

        public Node(int data){
    
    
            this.data=data;
        }

        @Override
        public String toString() {
    
    
            return "Node{" +
                    "data=" + data +
                    ", next=" + next +
                    '}';
        }
    }
}

Interview: Löschen Sie alle Knoten in der verknüpften Liste, die gleich val sind:

 //todo  删除链表中等于给定值val的所有节点
    public static Node deleteByVal(Node head,int val){
    
    
        Node tmp=head;
        int index=0;
        while (tmp!=null){
    
    
            index++;
            if (tmp.data==val){
    
    
               delete_index(index,head);
                index--;
            }
            tmp=tmp.next;
        }
        return head;
    }
//todo  删除链表中等于给定值val的所有节点
    public static Node removeVal(Node head,int val){
    
    
        if (head==null){
    
    
            return null;
        }
        head.next = removeVal(head.next, val);
        return head.data==val?head.next:head;
    }

Ausführliche Erklärung der rekursiven Lösung:
Fügen Sie hier eine Bildbeschreibung ein
Interview: Erstellung und Durchquerung eines Binärbaums

package algorithm_;
import java.util.*;
/**
 * @author brett
 * @date 2022-12-10 20:05:17
 */
public class BinaryTree {
    
    

    public static void main(String[] args) {
    
    
        LinkedList<Integer> list = new LinkedList<>(
                Arrays.asList(8,7,6,null,null,5,null,null,9,4,1,null,null,null,3,10)
        );
        TreeNode root = createTree(list);
//        System.out.println("前序遍历...");
//        preOrder(root);
//        System.out.println("中序遍历...");
//        inOrder(root);
//        System.out.println("非递归前序遍历...");
//        preOrder2(root);
//        System.out.println("非递归中序遍历...");
//        inOrder2(root);
//        System.out.println("后序遍历...");
//        postOrder(root);
//        System.out.println("非递归中序遍历...");
//        postOrder2(root);
        System.out.println("非递归层序遍历...");
        levelOrder(root);
        System.out.println("递归层序遍历...");
        levelOrder2(Collections.singletonList(root));
    }

    //递归--创建二叉树
    public static TreeNode createTree(LinkedList<Integer> list){
    
    
        TreeNode node=null;
        if (list==null || list.isEmpty()){
    
    
            return null;
        }
        Integer data = list.removeFirst();
        if (data!=null){
    
    
            node=new TreeNode(data);
            node.left=createTree(list);
            node.right=createTree(list);
        }
        return node;
    }

    //前序遍历
    public static void preOrder(TreeNode node){
    
    
        if (node==null){
    
    
            return;
        }
        System.out.println(node.data);
        preOrder(node.left);
        preOrder(node.right);
    }

    //中序遍历
    public static void inOrder(TreeNode node){
    
    
        if (node==null){
    
    
            return;
        }
        inOrder(node.left);
        System.out.println(node.data);
        inOrder(node.right);
    }

    //后序遍历
    public static void postOrder(TreeNode node){
    
    
        if (node==null){
    
    
            return;
        }
        postOrder(node.left);
        postOrder(node.right);
        System.out.println(node.data);
    }

    //非递归前序遍历
    public static void preOrder2(TreeNode root){
    
    
        Stack_Tree stackTree = new Stack_Tree(10);
        TreeNode tmp=root;
        while (tmp!=null || !stackTree.isEmpty()){
    
    
            while (tmp!=null){
    
    
                System.out.println(tmp.data);
                stackTree.push(tmp);
                tmp=tmp.left;
            }
            if (!stackTree.isEmpty()){
    
    
                tmp=stackTree.pop();
                tmp=tmp.right;
            }
        }
    }
    //非递归中序遍历
    public static void inOrder2(TreeNode root){
    
    
        Stack_Tree stackTree = new Stack_Tree(10);
        TreeNode tmp=root;
        while (tmp!=null || !stackTree.isEmpty()){
    
    
            while (tmp!=null){
    
    
                stackTree.push(tmp);
                tmp=tmp.left;
            }
            if (!stackTree.isEmpty()){
    
    
                tmp=stackTree.pop();
                System.out.println(tmp.data);
                tmp=tmp.right;
            }
        }
    }
    //非递归后序遍历
    public static void postOrder2(TreeNode root){
    
    
        Stack_Tree stackTree = new Stack_Tree(10);
        TreeNode tmp=root;  //当前访问的节点
        TreeNode lastVisit=null;  //标记上一次访问的节点
        while (tmp!=null){
    
    
            stackTree.push(tmp);
            tmp=tmp.left;
        }
        while (!stackTree.isEmpty()) {
    
    
            tmp=stackTree.pop();//弹出栈顶元素
            //一个根节点被访问的前提是:无右子树或右子树已被访问过
            if (tmp.right!=null && tmp.right!=lastVisit){
    
    
                //根节点再次入栈
                stackTree.push(tmp);
                //进入右子树,且可以肯定右子树一定不为空
                tmp=tmp.right;
                while (tmp!=null){
    
    
                    //再走到左子树最左边
                    stackTree.push(tmp);
                    tmp=tmp.left;
                }
            }else {
    
    
                //访问
                System.out.println(tmp.data);
                //修改最近被访问的节点
                lastVisit = tmp;
            }
        }
    }

    //层序遍历
    public static void levelOrder(TreeNode root){
    
    
        Queue queue = new Queue(10);
        queue.enQueue(root);
        while (!queue.isEmpty()){
    
    
            TreeNode tmp = queue.deQueue();
            System.out.println(tmp.data);
            if (tmp.left!=null){
    
    
                queue.enQueue(tmp.left);
            }
            if (tmp.right!=null){
    
    
                queue.enQueue(tmp.right);
            }
        }
    }

    //层序遍历递归实现
    public static void levelOrder2(List<TreeNode> list){
    
    
        if (list.size()==0)
            return;
        List<TreeNode> list2=new ArrayList<>();
        for (TreeNode e:list) {
    
    
            System.out.println(e.data);
            if (e.left!=null){
    
    
                list2.add(e.left);
            }
            if (e.right!=null){
    
    
                list2.add(e.right);
            }
        }
        levelOrder2(list2);
    }

    static class TreeNode{
    
    
        //数据域
        public int data;
        //左子树
        public TreeNode left;
        //右子树
        public TreeNode right;

        public TreeNode(int data){
    
    
            this.data=data;
        }
    }
    static class Stack_Tree{
    
    
        //数据域
        public TreeNode[] arr;
        //栈有效长度
        public int size;

        public Stack_Tree(int capacity){
    
    
            arr=new TreeNode[capacity];
            this.size=0;
        }
        //出栈
        public TreeNode pop(){
    
    
            if (this.size==0){
    
    
                throw new IndexOutOfBoundsException("栈空");
            }
            TreeNode remove_data = this.arr[size - 1];
            this.size--;
            return remove_data;
        }
        //入栈
        public void push(TreeNode node){
    
    
            if (this.size==this.arr.length){
    
    
                throw new IndexOutOfBoundsException("栈满");
            }
            this.arr[this.size]=node;
            this.size++;
        }
        //判断栈是否为空
        public boolean isEmpty(){
    
    
            return this.size == 0;
        }
    }
    static class Queue{
    
    
        TreeNode[] arr;  //存储数据
        int front;  //头指针
        int rear;  //尾指针

        public Queue(int capacity){
    
    
            arr=new TreeNode[capacity];
        }

        //入队操作
        public void enQueue(TreeNode node){
    
    
            //判断是否队满
            if ((rear+1)%this.arr.length==front){
    
    
                throw new IndexOutOfBoundsException("队列已经满了");
            }
            this.arr[rear]=node;
            rear=(rear+1)%this.arr.length;
        }
        //出队操作
        public TreeNode deQueue(){
    
    
            //判断是否对空
            if (rear==front){
    
    
                throw new IndexOutOfBoundsException("队列已经空了");
            }
            TreeNode remove_data=this.arr[front];
            front=(front+1)%this.arr.length;
            return remove_data;
        }
        //输出队列中所有元素
        public void output(){
    
    
            for (int i=front;i!=rear;i=(i+1)%this.arr.length){
    
    
                System.out.println(this.arr[i]);
            }
        }
        //判断队空
        public boolean isEmpty(){
    
    
            return rear==front;
        }
    }
}

Acho que você gosta

Origin blog.csdn.net/qq_49472679/article/details/128200922
Recomendado
Clasificación