数据结构与算法--排序

希尔排序:①   先取一个正整数d1(d1<n)作为第一个增量,将全部n个记录分成d1组,把所有相隔d1的记录放在一组中,即对于每个k(k=1, 2,  … d1),R[k], R[d1+k], R[2d1+k] , …分在同一组中,在各组内进行直接插入排序。这样一次分组和排序过程称为一趟希尔排序;
②   取新的增量d2<d1,重复①的分组和排序操作;直至所取的增量di=1为止,即所有记录放进一个组中排序为止。

 public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int[] arr=new int[8];
        for (int i = 0; i <8; i++) {
            arr[i]=(int)(Math.random()*8000);
        }
        System.out.println("初始数据为:"+Arrays.toString(arr));
        Date date1=new Date();
      //  SimpleDateFormat simpleDateFormat=new SimpleDateFormat(seconds);
      //  String str1=simpleDateFormat.format(date1);
       // System.out.println("希尔排序前的时间是:"+date1);
        shellSort2(arr);
        Date date2=new Date();
      //  String str2=simpleDateFormat.format(date2);
       // System.out.println("希尔排序后的时间是:"+date2);
        }
        //希尔排序【移位式】
    public static void shellSort(int[] arr){
        int temp=arr.length/2;
        int t=0;  //临时变量
        int j=0;
        int insertdata=0;
        int sub=0;
        int time=1;
        while(temp>0){
            for (int i = temp; i <arr.length; i++) {
                insertdata=arr[i];
                sub=i;j=i-temp;
                while(j>=0&&insertdata<=arr[j]){
                    sub=j; //保存数据
                    arr[j+temp]=arr[j];
                    j-=temp;
                }
                arr[sub]=insertdata;
            }
            System.out.printf("第%d次变化的的数据为:",time++);
            System.out.println(Arrays.toString(arr));
            temp=temp/2;
        }
    }
    //希尔排序【变换式】
    public static void shellSort2(int[] arr){
        int temp=arr.length/2;
        int t=0;  //临时变量
        int time=1;
        while(temp>0){
            for (int i = temp; i <arr.length; i++) {
                for (int j = i-temp; j >=0 ; j-=temp) {
                    if(arr[j+temp]<arr[j]){  //直接交换数据
                        t=arr[j];
                        arr[j]=arr[j+temp];
                        arr[j+temp]=t;
                    }
                }
            }
            System.out.printf("第%d次变化的的数据为:",time++);
            System.out.println(Arrays.toString(arr));
            temp=temp/2;
        }
    }


 

冒泡排序:依次比较相邻的两个记录的关键字,若两个记录是反序的(即前一个记录的关键字大于后前一个记录的关键字),则进行交换,直到没有反序的记录为止。

 public class BubbleSort{
 2      public static void main(String[] args){
 3          int score[] = {67, 69, 75, 87, 89, 90, 99, 100};
 4          for (int i = 0; i < score.length -1; i++){    //最多做n-1趟排序
 5              for(int j = 0 ;j < score.length - i - 1; j++){    
//对当前无序区score[0......length-i-1]进行排序(j的范围很关键,这个范围是在逐步缩小的)
 6                  if(score[j] < score[j + 1]){    //把小的值交换到后面
 7                      int temp = score[j];
 8                      score[j] = score[j + 1];
 9                      score[j + 1] = temp;
10                  }
11              }            
12              System.out.print("第" + (i + 1) + "次排序结果:");
13              for(int a = 0; a < score.length; a++){
14                  System.out.print(score[a] + "\t");
15              }
16              System.out.println("");
17          }
18              System.out.print("最终排序结果:");
19              for(int a = 0; a < score.length; a++){
20                  System.out.print(score[a] + "\t");
21         }
22      }
23  }

快速排序:通过一趟排序,将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,再分别对这两部分记录进行下一趟排序,以达到整个序列有序。

void Quick_Sort(int *arr, int begin, int end){
    if(begin > end)
        return;
    int tmp = arr[begin];
    int i = begin;
    int j = end;
    while(i != j){
        while(arr[j] >= tmp && j > i)
            j--;
        while(arr[i] <= tmp && j > i)
            i++;
        if(j > i){
            int t = arr[i];
            arr[i] = arr[j];
            arr[j] = t;
        }
    }
    arr[begin] = arr[i];
    arr[i] = tmp;
    Quick_Sort(arr, begin, i-1);
    Quick_Sort(arr, i+1, end);
}

 简单选择排序(Simple Selection Sort ,又称为直接选择排序)的基本操作是:通过n-i次关键字间的比较,从n-i+1个记录中选取关键字最小的记录,然后和第i个记录进行交换,i=1, 2, … n-1 。

1.工作原理

在未排序序列中找到最小(大)的元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)的元素,存放到已排序序列的末尾,直到所有元素排序完。

2.对于 n 个元素的时间复杂度为 O(n^2);

3.n比较大的话,效率也会与冒泡排序类似,不稳定。

void seletSort(int a[], int len)

{

    int i, j, k;

    for (i = 0; i < len; i++)

    {

        k = i;   //初始化最小的标记

        for (j = i; j < len; j++)

        {

            if (a[j] < a[k])

            {

                k = j;

            }

        }

        int temp = a[i];  //交换值

        a[i] = a[k];

        a[k] = temp;

    }

}

堆排序:由堆的定义知,堆是一棵以k1为根的完全二叉树。若对该二叉树的结点进行编号(从上到下,从左到右),得到的序列就是将二叉树的结点以顺序结构存放,堆的结构正好和该序列结构完全一致。
 

   public static void heapSort(int[] arr) {
        //1.构建大顶堆
        for (int i = arr.length / 2 - 1; i >= 0; i--) {
            //从第一个非叶子结点从下至上,从右至左调整结构
            adjustHeap(arr, i, arr.length);
        }
        //然后继续调整堆,再将堆顶元素与末尾元素交换,得到第二大元素。如此反复进行交换、重建、交换。
        //2.调整堆结构+交换堆顶元素与末尾元素
        for (int j = arr.length - 1; j > 0; j--) {
            swap(arr, 0, j);//将堆顶元素与末尾元素进行交换
            adjustHeap(arr, 0, j);//重新对堆进行调整
        }
    }
    /**
     * 调整大顶堆(仅是调整过程,建立在大顶堆已构建的基础上, 也就是说只调用一次,并没有得到大顶堆)
     * 就是将arr[i] 的值放到本次 调整过程中适当的位置。
     * @param arr    : 数组
     * @param i      : 非叶子节点的索引
     * @param length : 对多少个元素进行调整,这个length是逐渐减少的..
     */
    public static void adjustHeap(int[] arr, int i, int length) {
        int temp = arr[i];//先取出当前元素i
        for (int k = i * 2 + 1; k < length; k = k * 2 + 1) {//从i结点的左子结点开始,也就是2*i+1处开始
            if (k + 1 < length && arr[k] < arr[k + 1]) {//如果左子结点小于右子结点,k指向右子结点
                k++;
            }
            if (arr[k] > temp) {//如果子节点大于父节点,将子节点值赋给父节点(不用进行交换)
                arr[i] = arr[k];//把较大的值,赋给当前节点
                i = k;//i 指向k,继续循环比较
            } else {
                break;
            }
        }
        arr[i] = temp;//将temp值放到最终的位置
    }
    public static void swap(int[] arr, int a, int b) {
        int temp = arr[a];
        arr[a] = arr[b];
        arr[b] = temp;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值