排序算法

public class Sort{

  /**
    *冒泡排序(由小到大)
    *思路:对于给定的n个记录,从最后一个记录开始依次对相邻的两个记录进行比较,当后面的记录小于前面的记录时,交换位置,
    *进行一轮比较和换位之后,n个记录中的最小记录位于第1位;然后对后n-1个记录进行第二轮比较;重复该过程直到进行比较的记录只剩下一个为止.
    */
  public void bubble_sort(int [] a){
     for(int i = 0;i < a.length;i++){
        for(int j = a.length - 1;j > i;j--){
           if(a[j] < a[j-1]){
              int temp = a[j];
              a[j] = a[j-1];
              a[j-1] = temp;
           }
        }
     }
  }
  /**
    *选择排序(由小到大)
    *思路:对于给定的一组记录,经过第一轮比较之后得到最小的记录,然后将该记录与第一个记录的位置交换;
    *接着对不包括第一个记录的其他记录进行第二轮比较,得到最小记录并与第二个记录进行位置交换;
    *重复该过程,直到进行比较的记录只有一个为止.
    */
  public void select_sort(int [] a){
     for(int i = 0;i < a.length;i++){
        int min = a[i];
        int flag = i;
        for(int j = a.length - 1;j > i;j){
           if(a[j] < min){
              min = a[j];
              flag = j;
           }
        }
        if(flag != i){
          a[flag] = a[i];
          a[i] = min;
        }
     }
  }
  /**
    *插入排序(由小到大)
    *思路:对于给定的一组记录,初始时假设第一个记录自成一个有序序列,其余记录为无序序列;
    *接着从第二个记录开始,按照记录的大小依次将当前处理的记录插入到其之前的有序序列中,直到最后一个记录插入到有序序列中为止.
    */
  public void insert_sort(int [] a){
     for(int i = 1;i < a.length;i++){
       if(a[i] < a[i-1]){
          int temp = a[i];
          int j = i;
          while(j >= 1 && a[j-1] > temp){
             a[j] = a[j-1];
             j -- ;
          }
          a[j] = temp;
       }
     }
  }
  /**
    *希尔排序(由小到大)
    *思路:先将待排序的数组元素分成多个子序列,使得每个子序列的元素个数相对较少,然后对各个子序列分别进行直接插入排序,
    *     待整个待排序序列"基本有序"后,最后对所有元素进行一次直接插入排序.
    *希尔排序步骤:
    *1.选择一个步长序列t1,t2,...,tk,满足ti>tj(i<j),且tk=1;
    *2.按步长序列个数k,对待排序序列进行k趟排序;
    *3.每趟排序,根据对应的步长ti,将待排序列分割成ti个子序列,分别对各个子序列进行直接插入排序.
    */
  public void shell_sort(int [] a){
     int len = a.length;
     for(int h = len/2;h > 0;h = h/2){//h表示步长
        for(int i = h;i < len;i++){
           if(a[i] < a[i-h]){
             int temp = a[i];
             int j = i;
             while(j >= h && a[j-h] > temp){
                a[j] = a[j-h];
                j = j-h;
             }
             a[j] = temp;
           }
        }
     }
  }



  /**
    *堆排序(由小到大)
    *思路:对于给定的n个记录,初始时把这些记录看作一颗顺序存储的二叉树,然后将其调整为一个大顶堆,
    *     然后将堆的最后一个元素与堆顶元素(即二叉树的根节点)进行交换后,堆的最后一个元素即为最大记录;
    *     接着将前n-1个记录(即不包括最大记录)重新调整为一个大顶堆,再将堆顶元素与当前堆的最后一个元素进行交换后得到次最大记录;
    *     重复该过程直到调整的堆中只剩一个元素为止,即该元素为最小记录,此时得到一个有序序列.
    *简化思路:1.建立大顶堆2.交换第一个元素与最后一个元素的值3.重复以上步骤,不过每次参与建堆的元素个数比上一次减一
    */
  public void heap_sort(int [] a){
     int len = a.length;
     for(int i = len/2;i >= 0;i--){//从下往上,从右往左建立初始大顶堆
        heap_adjust(a,i,len-1);
     }

     for(int i = len-1;i > 0;i--){
        int temp = a[0];
        a[0] = a[i];
        a[i] = temp;
        head_adjust(a,0,i-1);
     }

  }
  public void heap_adjust(int [] a,int parent,int len){
     int temp = a[parent];
     for(int i = 2*parent + 1;i <= len;i = 2*i + 1){
        if(i+1 <= len && a[i+1] > a[i]){
           i = i + 1;
        }
        if(a[i] < temp){
          break;
        }
        a[parent] = a[i];
        a[i] = temp;
        parent = i;
     }
  }
  /**
    *归并排序(由小到大)
    *思路:对于给定的n个记录,首先将每两个相邻长度为1的子序列进行归并,得到n/2(向上取整)个长度为2或1的有序子序列,再将其两两归并,
    *反复执行此过程,直到得到一个有序序列.
    *归并排序的关键两步:1.划分半子表2.合并半子表
    */
  public void merge_sort(int [] a){
    for(int gap = 1;gap <= a.length/2;gap = gap*2){
      merge_sort1(a,gap);
    }
  }
  public void merge_sort1(int [] a,int gap){
     int i;
     for(i = 0;i + 2*gap-1 < a.length;i = i + 2*gap){
        merge(a,i,i+gap,i+2*gap-1);
     }
     if(i + gap < a.length){
       merge(a,i,i+gap,a.length-1);
     }
  }
  public void megre(int [] a,int low,int mid,int high){
     if(low >= mid || mid > high) return ;
     int i = low,j = mid;
     int n = 0;
     int [] temp = new int [high - low + 1];
     while(i < mid && j <= high){
        if(a[i] <= a[j]){
           temp[n++] = a[i++];
        }else{
           temp[n++] = a[j++];
        }
     }
     while(i < mid){
        temp[n++] = a[i++];
     }
     while(j <= high){
        temp[n++] = a[j++];
     }

     for(int k=0;k < temp.length;k++){
       a[k+low] = temp[k];
     }
  }
  /**
    *快速排序(由小到大)
    *思路:对于给定的n个记录,通过一趟排序之后,将原序列分为两部分,其中前一部分的所有记录均比后一部分的所有记录小,
    *     然后再依次对前后两部分的记录进行快速排序,递归该过程,直到序列中所有记录均有序为止.
    *算法步骤:
    *1.分解,将输入的序列a[m...n]划分为两个非空子序列a[m...k]和a[k+1...n],使a[m...k]中任一元素的值不大于a[k+1...n]中的任一元素的值;
    *2.递归求解,通过递归调用快速排序算法分别对a[m...k]和a[k+1...n]进行排序;
    *3.合并:由于分解出的两个子序列的排序是就地进行,所以在a[m...k]和a[k+1...n]都排好序后不需要执行任何计算,a[m...n]就已经排好序.
    */
  public vodi quick_sort(int [] a){
    quick_sort1(a,0,a.length-1);
  }
  public void quick_sort1(int [] a,int start,int end){
    if(start >= end) return ;
    int pivot = partition(a,start,end);
    quick_sort1(a,start,pivot-1);
    quick_sort1(a,pivot+1,end);
  }
  public int partition(int [] a,int start,int end){
    int temp = a[start];
    int left = start,right = end;
    while(left < right){
      while(right>left && a[right] >= temp){
        right-- ;
      }
      if(right > left){
        a[left] = a[right];
        a[right] = temp;
      }
      while(left < right && a[left] <= temp){
        left++;
      }
      if(left < right){
        a[right] = a[left];
        a[left] = temp; 
      }
    }
    return left;
  }


  /**
    *计数排序(由小到大)
    *思路:用待排序的数作为计数数组的下标,统计每个数字的个数,然后依次输出即可得到有序序列.
    *算法步骤:
    *1.找出待排序的数组中最大的元素;
    *2.统计数组中每个值为i的元素出现的次数,存入数组C的第i项;
    *3.反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1.
    */
  public void count_sort(int [] a){
     if(a == null || a.length == 0) return ;
     //找到待排序数组的最大值
     int max = a[0];
     for(int i = 1;i < a.length;i++){
        if(a[i] > max){
          max = a[i];
        }
     }
     int [] c = new int [max+1];
     for(in i = 0;i < a.length;i++){
        c[a[i]]++;
     }
     //计数排序
     int k = 0;
     for(int i = 0;i < max+1;i++){
        while(c[i] != 0){
          a[k++] = i;
          c[i]--;
        }
     }
  }
  /**
    *桶排序(由小到大)
    *思路:桶排序是计数排序的升级版.假设输入数据服从均匀分布,将数据分到有限数量的桶里,每个桶再分别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排).
    *算法步骤:
    *1.设置一个定量的数组当作空桶;
    *2.遍历输入数据,并且把数据一个一个放到对应的桶里去;
    *3.对每个不是空的桶进行排序;
    *4.从不是空的桶里把排好序的数据拼接起来.
    */
  public void bucket_sort(int [] a){
     if(a == null || a.length == 0) return ;
     int bucketNums = 10;//这里默认10,规定待排数[0,100)
     //桶的索引
     ArrayList<LinkedList<Integer>> buckets = new ArrayList<>();
     for(int i = 0;i < bucketNums;i++){
        //使用链表比较合适
        buckets.add(new LinkedList<Integer>());
     }
     //划分桶
     for(int i = 0;i < a.length;i++){
         buckets.get(f(a[i])).add(a[i]);
     }
     //对每个桶进行排序
     for(int i = 0;i < bucketNums;i++){
         if(!buckets.get(i).isEmpty()){
            Collections.sort(buckets.get(i));//快速排序
         }
     }
     //还原排好序的数组
     int k = 0;
     for(LinkedList<Integer> bucket : buckets){
        if(!bucket.isEmpty()){
           for(int elem : bucket){
              a[k++] = elem;
           }
        }
     }
  }
  //桶的映射函数
  public int f(int n){
     return n/10;
  }

  /**
    *基数排序(由小到大)
    *思路:基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。
    *算法步骤:
    *1.取得数组中的最大数,并取得位数;
    *2.a为原始数组,从最低位开始取每个位组成radix数组;
    *3.对radix进行计数排序(利用计数排序适用于小范围数的特点).
    */
    public void radix_sort(int [] a){
      if(a == null || a.length == 0) return ;
      int maxBit = getMaxBit(a);//得到最大位数
      for(int i = 1;i <= maxBit;i++){
        ArrayList<LinkedList<Integer>> buf = distribute(a,i);//分配
        collect(a,buf);//收集
      }
    }
    //获取最大位数
    public int getMaxBit(int [] a){
       int max = 0;
       for(int elem : a){
         int len = (elem + "").length();
         if(len > max) max = len;
       }
       return max;
    }
    //分配
    public ArrayList<LinkedList<Integer>> distribute(int [] a,int iBit){
        ArrayList<LinkedList<Integer>> buf = new ArrayList<>();
        for(int i = 0;i < 10;i++){
           buf.add(new LinkedList<Integer>());
        }
        for(int i = 0;i < a.length;i++){
           buf.get(getNBit(a[i],iBit)).add(a[i]);
        }
        return buf;
    }
    public int getNBit(int x,int n){//获取x的第n位,如果没有则为0
       String sx = x + "";
       if(sx.length() < n){
          return 0;
       }else{
          return sx.charAt(sx.length() - n) - '0';
       }
    }
    //收集
    public void collect(int [] a,ArrayList<LinkedList<Integer>> buf){
       int k = 0;
       for(LinkedList<Integer> bucket : buf){
          if(!bucket.isEmpty()){
            for(int elem : bucket){
              a[k++] = elem;
             }
          }
       }
    }

}
内容概要:本文探讨了在MATLAB/SimuLink环境中进行三相STATCOM(静态同步补偿器)无功补偿的技术方法及其仿真过程。首先介绍了STATCOM作为无功功率补偿装置的工作原理,即通过调节交流电压的幅值和相位来实现对无功功率的有效管理。接着详细描述了在MATLAB/SimuLink平台下构建三相STATCOM仿真模型的具体步骤,包括创建新模型、添加电源和负载、搭建主电路、加入控制模块以及完成整个电路的连接。然后阐述了如何通过对STATCOM输出电压和电流的精确调控达到无功补偿的目的,并展示了具体的仿真结果分析方法,如读取仿真数据、提取关键参数、绘制无功功率变化曲线等。最后指出,这种技术可以显著提升电力系统的稳定性与电能质量,展望了STATCOM在未来的发展潜力。 适合人群:电气工程专业学生、从事电力系统相关工作的技术人员、希望深入了解无功补偿技术的研究人员。 使用场景及目标:适用于想要掌握MATLAB/SimuLink软件操作技能的人群,特别是那些专注于电力电子领域的从业者;旨在帮助他们学会建立复杂的电力系统仿真模型,以便更好地理解STATCOM的工作机制,进而优化实际项目中的无功补偿方案。 其他说明:文中提供的实例代码可以帮助读者直观地了解如何从零开始构建一个完整的三相STATCOM仿真环境,并通过图形化的方式展示无功补偿的效果,便于进一步的学习与研究。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值