数据结构排序算法的概念是从网上抄录的:

基本概念:

1、  排序:按照一定的关键字,将一个序列排列成想要得到的一个新的序列。

2、  内部排序和外部排序:整个排序过程完全在内存中进行,叫做内部排序。数据量较大需要借助外部存储设备才能完成,叫做外部排序。

3、  主关键字和此关键字:

4、  排序的稳定性:对于相同的元素来说,在排序之前和之后的书讯是一样的,那么这种排序就是稳定的排序,如果顺序发生了变化,那么就是不稳定排序。

插入类排序:

(一)   思想:在一个已经排好序的序列中,将未被排进的元素按照原先的规定插入到指定位置。

(二)   分类:

1、  直接插入排序:

①   思想:最基本的插入排序,将第i个插入到前i-1个中的适当位置。

②   时间复杂度:T(n) = O(n)。

③   空间复杂度:S(n) = O(1)。

④   稳定性:稳定排序。循环条件while(r[0].key < r[j].key)保证的。

⑤   程序:

 /**
  * 直接插入排序:
  * 1.从第一个元素开始,该元素可以认为已经被排序 
  * 2.取出下一个元素,在已经排序的元素序列中从后向前扫描
  * 3.如果该元素小于前面的元素(已排序),则依次与前面元素进行比较如果小于则交换,直到找到大于该元素的就则停止;
  * 4.如果该元素大于前面的元素(已排序),则重复步骤2 5.重复步骤2~4 直到所有元素都排好序 。
  * 
  * @param a
  */
 public static void insert(int[] a) {
  for (int i = 1; i < a.length; i++) {
   int key = a[i];
   for (int j = i - 1; j >= 0; j--) {
    if (key < a[j]) {
     int temp = a[j];
     a[j] = key;
     a[i] = temp;
     i = j;
    }
   }
  }
 }

2、  折半插入排序:

①   思想:因为是已经确定了前部分是有序序列,所以在查找插入位置的时候可以用折半查找的方法进行查找,提高效率。

②   时间复杂度:比较时的时间减为O(n㏒n),但是移动元素的时间耗费未变,所以总是得时间复杂度还是O(n)。

③   空间复杂度:S(n) = O(1)。

④   稳定性:稳定排序。

⑤   程序:

 /**
  * 折半插入排序:
  * 在将一个新元素插入已排好序的数组的过程中,寻找插入点时, 将待插入区域的首元素设置为a[low],末元素设置为a[high],
  * 比较时将待插入元素与a[m],其中m=(low+high)/2相比较,如果比参考元素大,
  * 则选择a[low]到a[m-1]为新的插入区域(即high=m-1), 否则选择a[m+1]到a[high]为新的插入区域(即low=m+1),
  * 如此直至low<=high不成立,即将此位置之后所有元素后移一位, 并将新元素插入a[high+1]。
  * 
  * @param a
  */
 public static void binaryInsert(int[] a) {
  // {1, 5, 5, 3, 4, 3,2}
  for (int i = 1; i < a.length; i++) {
   int key = a[i];
   int low = 0;
   int high = i - 1;
   while (low <= high) {
    int mid = (low + high) / 2;
    if (key < a[mid]) {
     high = mid - 1;
    } else {
     low = mid + 1;
    }
   }
   System.out.println("low:" + low + ",high:" + high + ",i:" + i
     + ",key:" + key);
   for (int j = i; j > high + 1; j--) {
    a[j] = a[j - 1];
   }
   a[high + 1] = key;
  }
 }

3、shell排序

交换类排序:

(一)   思想:通过交换逆序元素进行排序的方法。

(二)   分类:

1、  冒泡排序:

①   思想:反复扫描待排序序列,在扫描的过程中顺次比较相邻的两个元素的大小,若逆序就交换位置。第一趟,从第一个数据开始,比较相邻的两个数据,(以升序为例)如果大就交换,得到一个最大数据在末尾;然后进行第二趟,只扫描前n-1个元素,得到次大的放在倒数第二位。以此类推,最后得到升序序列。如果在扫描过程中,发现没有交换,说明已经排好序列,直接终止扫描。所以最多进行n-1趟扫描。

②   时间复杂度:T(n) = O(n)。

③   空间复杂度:S(n) = O(1)。

④   稳定性:稳定排序。

⑤   程序:

 /**
  * 冒泡排序:
  * 依次比较相邻的两个数,将小数放在前面,大数放在后面。 即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。
  * 然后比较第2个数和第3个数,将小数放前,大数放后,如此继续, 直至比较最后两个数,将小数放前,大数放后。 至此第一趟结束,将最大的数放到了最后。
  * 依次执行以上步骤a.leng-1次,排序完成。
  * 
  * @param a
  */
 public static void bubble(int[] a) {
  // {1, 5, 5, 3, 4, 3,2}
  for (int i = 1; i < a.length; i++) {
   for (int j = 0; j < a.length - i; j++) {
    if (a[j + 1] < a[j]) {
     int temp = a[j + 1];
     a[j + 1] = a[j];
     a[j] = temp;
    }
   }
  }
 }

2、  快速排序:

①   思想:冒泡排序一次只能消除一个逆序,为了能一次消除多个逆序,采用快速排序。以一个关键字为轴,从左从右依次与其进行对比,然后交换,第一趟结束后,可以把序列分为两个子序列,然后再分段进行快速排序,达到高效。

②   时间复杂度:平均T(n) = O(n㏒n),最坏O(n)。

③   空间复杂度:S(n) = O(㏒n)。

④   稳定性:不稳定排序。{3, 2, 2}

⑤   程序:

 /**
  * 快速排序:
  * 一趟快速排序的算法是: 
  * 1)设置两个变量l、h,排序开始的时候:l=0,h=N-1;
  * 2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];
  * 3)从j开始向前搜索,即由后开始向前搜索,找到第一个小于key的值A[j],将A[j]和A[i]互换,然后h--;
  * 4)从i开始向后搜索,即由前开始向后搜索,找到第一个大于key的A[i],将A[i]和A[j]互换,然后l++;
  *  5)重复第3、4步,直到l==h
  * 
  * @param a
  */
 public static void quick(int[] a, int l, int h) {
  int low = l;
  int high = h;
  int key = a[low];
  while (low < high) {
   //从后往前找
   while (low < high && key < a[high]) {
    high--;
   }
   if (low < high) {
    int temp = a[high];
    a[high] = a[low];
    a[low] = temp;
    low++;
   }
   //从前往后找
   while (low < high && key > a[low]) {
    low++;
   }
   if (low < high) {
    int temp = a[high];
    a[high] = a[low];
    a[low] = temp;
    high--;
   }
  }
  if (low > l) {
   quick(a, l, low-1);
  }
  if (high < h) {
   quick(a, high+1, h);
  }
 }

选择类排序:

(一)   思想:每一趟在n – i + 1 ( i = 1,2, … , n - 1)个记录中选取关键字最小的记录作为有序序列中的第i个记录。

(二)   分类:

1、  简单选择排序:

①   思想:第一趟时,从第一个记录开始,通过n – 1次关键字的比较,从n个记录中选出关键字最小的记录,并和第一个记录进行交换。第二趟从第二个记录开始,选择最小的和第二个记录交换。以此类推,直至全部排序完毕。

②   时间复杂度:T(n) = O(n)。

③   空间复杂度:S(n) = O(1)。

④   稳定性:不稳定排序,{3, 3, 2}。

⑤   程序:

 /**
  * 选择排序:
  * 在第一趟遍历N个数据,找出其中最小的数值与第一个元素交换,
  * 第二趟遍历剩下的N-1个数据,找出其中最小的数值与第二个元素交换......
  * 第N-1趟遍历剩下的2个数据,找出其中最小的数值与第N-1个元素交换,
  * 至此选择排序完成。
  * @param a
  */
 public static void selectSort(int[] a) {
  //{ 1, 5, 5, 3, 4, 3, 2 };
  for(int i=1; i<a.length; i++) {
   int flag = i-1;
   for(int j=i; j<a.length; j++) {
    if(a[flag] > a[j]) {
     flag = j;
    }
   }
   if(flag != i-1) {
    int temp = a[flag];
    a[flag] = a[i-1];
    a[i-1] = temp;
   }
   toString(a);
  }
 }

3、  堆排序:

①   思想:把待排序记录的关键字存放在数组r[1…n]中,将r看成是一刻完全二叉树的顺序表示,每个节点表示一个记录,第一个记录r[1]作为二叉树的根,一下个记录r[2…n]依次逐层从左到右顺序排列,任意节点r[i]的左孩子是r[2i],右孩子是r[2i+1],双亲是r[i/2向下取整]。然后对这棵完全二叉树进行调整建堆。

②   时间复杂度:T(n) = O(n㏒n)。

③   空间复杂度:S(n) = O(1)。

④   稳定性:不稳定排序。{5, 5, 3}