一、冒泡排序
冒泡排序的原理是相邻元素进行比较,如果第一个元素比第二个元素大,那么交换第一个元素和第二个元素;再第二个元素和第三个元素比,如果第二个元素比第三个元素大,那么交换第二个元素和第三个元素;知道比较到最后一个元素,那么这一趟下类,数组中最大元素就在最后一个。再进行第二趟比较,方式和上面一样只是不用再比较最后一个元素了,因为第一趟最后一个元素就是最大的了。通过循环进行这样的比较直到没有元素需要比较了。
//交换函数
class Swap{
public static void swap(int[] a,int i,int j){
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
/**
* 冒泡排序
*/
class Bubble_Sort{
public static void bubbleSort(int[] a){
for(int i = 0;i<a.length;i++){
for(int j = 0;j<a.length-1-i;j++){
if(a[j] > a[j+1]){
Swap.swap(a, j, j+1);
}
}
}
System.out.print("冒泡排序:");
for (int var : a) {
System.out.print(var+",");
}
}
}
class Test{
public static void main(String[] args) {
int[] data = new int[]{5,6,1,3,7,8,4,2,0,9};
Bubble_Sort.bubbleSort(data);
}
}
二、定向冒泡排序(鸡尾酒排序)
定向冒泡排序是冒泡排序的改进,在冒泡排序的一趟比较中,我们不仅要把最大元素放到了最后面,还要将最小元素放到最左面,这就是定向冒泡排序的思想。我们可以定义2个变量left和right来记录未排好序的元素起始和末尾位置,一趟比较下来最小元素在左面就让left+1,最大元素在最右面就让right-1,这时我们只需比较left和right之间的元素就可以了。
//交换函数
class Swap{
public static void swap(int[] a,int i,int j){
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
/**
* 鸡尾酒排序
*/
class Cocktail_Sort{
public static void cocktailSort(int[] a){
int left =0;
int right = a.length-1;
while(left<right){
for(int j = left;j<right;j++){
if(a[j] > a[j+1]){
Swap.swap(a,j,j+1);
}
}
right--;
for(int j =right;j>left;j--){
if(a[j]<a[j-1]){
Swap.swap(a,j,j-1);
}
}
left++;
}
System.out.println("鸡尾酒排序:");
for (int var : a) {
System.out.print(var+",");
}
}
}
class Test{
public static void main(String[] args) {
int[] data = new int[]{5,6,1,3,7,8,4,2,0,9};
for (int var : data) {
System.out.print(var+",");
}
Cocktail_Sort.cocktailSort(data);
}
}
三、选择排序
选择排序的思想是在所有元素中找出最小元素,将最小元素放到第一个位置,再在剩下的元素中找到最小的元素,放在之前找的最小元素的后面,知道找完整个数组。具体实现过程是min记录最小元素的位置,假设未比较的数组中第一个元素就是最小的即min=0,通过循环把所有元素进行比较,如果有一个元素比最小元素要小,那么就把这个元素的位置给min,比较完所有元素就找到了哪个元素最小,如果最小元素不是第一个把最小元素与数组第一个元素交换。再从第二个元素开始进行如上操作,知道把整个数组找完。
//交换函数
class Swap{
public static void swap(int[] a,int i,int j){
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
class Selection_Sort{
public static void selectionSort(int[] a){
for(int i = 0;i<a.length-1;i++){
int min = i;
for(int j =i+1;j<a.length;j++){
if(a[j]<a[min]){
min = j;
}
}
if(min!=i){
Swap.swap(a,min,i);
}
}
System.out.println("选择排序:");
for (int var : a) {
System.out.print(var+",");
}
}
}
class Test{
public static void main(String[] args) {
int[] data = new int[]{5,6,1,3,7,8,4,2,0,9};
for (int var : data) {
System.out.print(var+",");
}
Selection_Sort.selectionSort(data);
}
}
四、选择排序改进
对于选择排序的改进思路和鸡尾酒排序一样,一趟循环直接找出最大和最小的位置,将最大的交换到最后的位置、最小的交换到第一个位置,但是要注意当最大的元素正好在最左面时,交换了最小元素和最左面的元素,这时最大元素的位置已经变了,要注意进行判断。
/**
*选择排序改进
*/
class Selection_Sort_OP{
public static void selectionSort_op(int[] a){
int left = 0;
int right = a.length-1;
while(left<right){
int max = right-1;
int min = left;
for(int j = left+1;j<=right;j++){
if(a[j]<a[min]){
min = j;
}
if(a[j]>a[max]){
max = j;
}
}
if(min!=left){
Swap.swap(a,min,left);
}
if( max == left){
max = min;
}
if(max !=right){
Swap.swap(a,max,right);
}
left++;
right--;
}
System.out.println("选择排序OP:");
for (int var : a) {
System.out.print(var+",");
}
}
}
class Test{
public static void main(String[] args) {
int[] data = new int[]{5,6,1,3,7,8,4,2,0,9};
for (int var : data) {
System.out.print(var+",");
}
System.out.println();
Selection_Sort_OP.selectionSort_op(data);
}
}
五、插入排序
插入排序类似我们抓扑克牌,我们假设我们左手的牌是有序的,现在我们又抓了一张牌,我们可以从后向前比较,直到找到一个位置这个位置之前的牌比我刚抓的牌小,这个位置之后的牌比我刚抓的牌大,我们就把抓的牌插入这个位置。实现过程是记录下已经排好序的元素的末尾,用一个变量来记录我们右手抓的牌,从后向前比较,找到位置,然后将这个位置后面的元素都向后移动一位,然后把右手抓的牌放到这个位置。
/**
* 插入排序
*/
class Insertion_Sort{
public static void insertionSort(int[] a){
for(int i = 1;i<a.length;i++){
int get = a[i];
int end = i - 1;
while(end >=0 && get < a[end]){
a[end+1] = a[end];
end --;
}
a[end+1] = get;
}
System.out.println("插入排序:");
for (int var : a) {
System.out.print(var+",");
}
}
}
class Test{
public static void main(String[] args) {
int[] data = new int[]{5,6,1,3,7,8,4,2,0,9};
for (int var : data) {
System.out.print(var+",");
}
System.out.println();
Insertion_Sort.insertionSort(data);
}
}
六、二分插入排序——插入排序的改进
插入排序算法需要从后向前不断比较手里的牌,而二分法是将手里的牌分成2部分,找出中间的牌,如果中间的牌比新抓的牌大,说明我要插入的位置在中间的牌左面,右面的牌就不用进行比较了。如果中间的牌比新抓的牌小,说明要插入的位置在中间的牌右面。选择好一面后,再对这一面进行二分直到找出要插入的位置。
当n较大时,二分插入排序的比较次数比直接插入排序的最差情况好得多,但比直接插入排序的最好情况要差,所当以元素初始序列已经接近升序时,直接插入排序比二分插入排序比较次数少。二分插入排序元素移动次数与直接插入排序相同,依赖于元素初始序列。
/**
* 二分插入排序
*/
class Insertion_Sort_Dichotomy{
public static void insertionSort_Dichotomy(int[] a){
for(int i = 1;i<a.length;i++){
int get = a[i];
int left = 0;
int right = i-1;
while(left <= right){
int mid = (left + right)/2;
if(a[mid]>=get){
right = mid - 1;
}else{
left = mid + 1;
}
}
int end = i - 1;
while(end>=left){
a[end+1] = a[end];
end--;
}
a[left] = get;
}
System.out.println("二分插入排序:");
for (int var : a) {
System.out.print(var+",");
}
}
}
class Test{
public static void main(String[] args) {
int[] data = new int[]{5,6,1,3,7,8,4,2,0,9};
for (int var : data) {
System.out.print(var+",");
}
System.out.println();
Insertion_Sort_Dichotomy.insertionSort_Dichotomy(data);
}
}