1、插入排序

在要排序的一组数中,假设前面(n-1) [n>=2] 个数已经是排好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。

直接插入排序是稳定的。算法时间复杂度O(n2)--[n的平方]

main()

{

int  a[10],j,i,m;

for(j=1;j<10;j++)

{

m=a[j];

for(i=j-1;i>=0;i--)

{

if(a[i]<m)

break;

else

a[i+1]=a[i];

}

a[i+1]=m;

}

}

 

加注释的版本:

void lnsertSort(SeqList R)
   { //对顺序表R中的记录R[1..n]按递增序进行插入排序
    int i,j;
    for(i=2;i<=n;i++) //依次插入R[2],…,R[n]
      if(R[i].key<R[i-1].key){//若R[i].key大于等于有序区中所有的keys,则R[i]
                              //应在原有位置上
        R[0]=R[i];j=i-1; //R[0]是哨兵,且是R[i]的副本
        do{ //从右向左在有序区R[1..i-1]中查找R[i]的插入位置
         R[j+1]=R[j]; //将关键字大于R[i].key的记录后移
         j-- ;
         }while(R[0].key<R[j].key); //当R[i].key≥R[j].key时终止
        R[j+1]=R[0]; //R[i]插入到正确的位置上
       }//endif
   }//InsertSort

 

 

2、希尔排序

D.L.shell于1959年在以他名字命名的排序算法中实现了这一思想。算法先将要排序的一组数按某个增量d分成若干组,每组中记录的下标相差d.对每组中全部元素进行排序,然后再用一个较小的增量对它进行,在每组中再进行排序。当增量减到1时,整个要排序的数被分成一组,排序完成。

下面的函数是一个希尔排序算法的一个实现,初次取序列的一半为增量,

以后每次减半,直到增量为1。

希尔排序是不稳定的。

 

void shell_sort(int *x, int n)

{

int h, j, k, t;

for (h=n/2; h>0; h=h/2) /*控制增量*/

{

for (j=h; j<n; j++) /*这个实际上就是上面的直接插入排序*/

{

t = *(x+j);

for (k=j-h; (k>=0 && t<*(x+k)); k-=h)

{

if(*(x+k)<t)

break;

else

*(x+k+h) = *(x+k);

}

*(x+k+h) = t;

}

}

}

3、冒泡排序

在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。

冒泡排序是稳定的。算法时间复杂度O(n2)--[n的平方]

main()

{

int a[10],i,j,k;

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

for(j=0;j<10-i;j++)

if(a[j]>a[j+1])

{

k=a[j];

a[j]=a[j+1];

a[j+1]=k;

}

}

 

 

4、快速排序

快速排序是对冒泡排序的一种本质改进。它的基本思想是通过一趟扫描后,使得排序序列的长度能大幅度地减少。在冒泡排序中,一次扫描只能确保最大数值的数移到正确位置,而待排序序列的长度可能只减少1。快速排序通过一趟扫描,就能确保以某个数为基准点的左边各数都比它小,右边各数都比它大。然后又用同样的方法处理它左右两边的数,直到基准点的左右只有一个元素为止。

显然快速排序可以用递归实现,当然也可以用栈化解递归实现。

快速排序是不稳定的。最理想情况算法时间复杂度O(nlog2n),最坏O(n2)

main()

{

int a[10],i;

quick_sort(a,0,9);

}

quick_sort(int L[],int first,int end)

{

int split;

if(end>first)

{

split=quick(first,end,L);//进行一次希尔排序,返回值为本次排序基准值的下标值

quick_sort(L,first,split-1);//上面的排序完成后再对基准点左右的数组进行同样的排序操作

quick_sort(L,split+1,end);

}

}

quick(int first,int end,int L[])

{

int left=first,right=end;

int key=L[first];

while(left<right)

{

while((left<right)&&(L[right]>=key))

right--;

if(left<right)

L[left++]=L[right];

while((left<right)&&(L[left]<=key))

left++;

if(left<right)

L[right--]=L[left];

}

L[left]=key;

return left;

}

 

 

5、选择排序

在要排序的一组数中,选出最小的一个数与第一个位置的数交换;然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止。

选择排序是不稳定的。算法复杂度O(n2)--[n的平方]

main()

{

int t,k,i,j,a[10];

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

{

k=i;

for(j=i+1;j<10;j++)

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

k=j;

t=a[i];

a[i]=a[k];

a[k]=t;

}

}

 

 

6、堆排序

堆排序是一种树形选择排序,是对直接选择排序的有效改进。堆的定义如下:具有n个元素的序列(h1,h2,...,hn),当且仅当满足(hi>=h2i,hi>=2i+1)或(hi<=h2i,hi<=2i+1)(i=1,2,...,n/2)

时称之为堆。在这里只讨论满足前者条件的堆。

由堆的定义可以看出,堆顶元素(即第一个元素)必为最大项。完全二叉树可以

很直观地表示堆的结构。堆顶为根,其它为左子树、右子树。初始时把要排序的数的序列看作是一棵顺序存储的二叉树,调整它们的存储顺序,使之成为一个堆,这时堆的根节点的数最大。然后将根节点与堆的最后一个节点交换。然后对前面(n-1)个数重新调整使之成为堆。依此类推,直到只有两个节点的堆,并对它们作交换,最后得到有n个节点的有序序列。

从算法描述来看,堆排序需要两个过程,一是建立堆,二是堆顶与堆的最后一个元素

交换位置。所以堆排序有两个函数组成。一是建堆的渗透函数,二是反复调用渗透函数

实现排序的函数。有最大堆和最少堆之分。

堆排序是不稳定的。算法时间复杂度O(nlog2n)。

功能:渗透建堆

void sift(int *x, int n, int s)

{

int t, k, j;

t = *(x+s); /*暂存开始元素*/

k = s;   /*开始元素下标*/

j = 2*k + 1; /*右子树元素下标*/

while (j<n)

{

/*判断是否满足堆的条件:满足就继续下一轮比较,否则调整。*/

if (j<n-1 && *(x+j) < *(x+j+1))

{

j++;

}

if (t<*(x+j)) /*调整*/

{

*(x+k) = *(x+j);

k = j; /*调整后,开始元素也随之调整*/

j = 2*k + 1;

}

else /*没有需要调整了,已经是个堆了,退出循环。*/

{

break;

}

}

*(x+k) = t; /*开始元素放到它正确位置*/

}

功能:堆排序

void heap_sort(int *x, int n)

{

int i, k, t;

int *p;

for (i=n/2-1; i>=0; i--)

{

sift(x,n,i); /*初始建堆*/

}

for (k=n-1; k>=1; k--)

{

t = *(x+0); /*堆顶放到最后*/

*(x+0) = *(x+k);

*(x+k) = t;

sift(x,k,0); /*剩下的数再建堆*/

}

}

7. 归并排序(Merge Sort)

利用"归并"技术来进行排序。归并是指将若干个已排序的子文件合并成一个有序的文件。
   1、算法基本思路
     设两个有序的子文件(相当于输入堆)放在同一向量中相邻的位置上:R[low..m],R[m+1..high],先将它们合并到一个局部的暂存向量R1(相当于输出堆)中,待合并完成后将R1复制回R[low..high]中。

(1)合并过程
     合并过程中,设置i,j和p三个指针,其初值分别指向这三个记录区的起始位置。合并时依次比较R[i]和R[j]的关键字,取关键字较小的记录复制到R1[p]中,然后将被复制记录的指针i或j加1,以及指向复制位置的指针p加1。
     重复这一过程直至两个输入的子文件有一个已全部复制完毕(不妨称其为空),此时将另一非空的子文件中剩余记录依次复制到R1中即可。

(2)动态申请R1
     实现时,R1是动态申请的,因为申请的空间可能很大,故须加入申请空间是否成功的处理。

2、归并算法
  void Merge(SeqList R,int low,int m,int high)
    {//将两个有序的子文件R[low..m]和R[m+1..high]归并成一个有序的
     //子文件R[low..high]
     int i=low,j=m+1,p=0; //置初始值
     RecType *R1; //R1是局部向量,若p定义为此类型指针速度更快
     R1=(ReeType *)malloc((high-low+1)*sizeof(RecType));
     if(! R1) //申请空间失败
       Error("Insufficient memory available!");
     while(i<=m&&j<=high) //两子文件非空时取其小者输出到R1[p]上
       R1[p++]=(R[i].key<=R[j].key)?R[i++]:R[j++];
     while(i<=m) //若第1个子文件非空,则复制剩余记录到R1中
       R1[p++]=R[i++];
     while(j<=high) //若第2个子文件非空,则复制剩余记录到R1中
       R1[p++]=R[j++];
     for(p=0,i=low;i<=high;p++,i++)
       R[i]=R1[p];//归并完成后将结果复制回R[low..high]
    } //Merge

8.二分法查找和二分法插入

首先申明,二分法查找只适用与已排序的数列,如果是混乱数列。。我也无能为力~

有一个数组 v 已经按升序排列了,数组 v 有 n=20 个元素。数组中有个元素 x,如何知道 x 位于该数组的第几位呢?

解决这个问题的一个普遍方法是二分法查找。下面是程序:

int binsearch(int x, int v[], int n) {    
   int low, high, mid;       
   low = 0;          
   high = n - 1;  
 while (low <= high) {                     
   mid = (low + high) / 2;                              
   if(x < v[mid])                                 
     high = mid - 1;                        
   else if (x > v[mid])                                      
     low = mid + 1;                         
   else                                              
     return mid;                              // 看看循环执行了多少次                               
 printf("mid = %d, low = %d, high = %d \n", mid, low, high); 
 }           
 return -1; //没有查找出来返回-1
}

思路很简单:首先将输入值 x 与数组 v 的中间元素比较,如果 x 小于中间的元素,则将 high 值设为 中间元素-1,同理,若 x 大于中间元素,则将中间元素 + 1作为 low,再在low 与 high之间进行查找

二分法插入排序 
算法思想简单描述:
在插入第i个元素时,对前面的0~i-1元素进行折半,先跟他们
中间的那个元素比,如果小,则对前半再进行折半,否则对后半
进行折半,直到left>right,然后再把第i个元素前1位与目标位置之间
的所有元素后移,再把第i个元素放在目标位置上。

二分法没有排序,只有查找。所以当找到要插入的位置时。移动必须从最后一个记录开始,向后移动一位,再移动倒数第2位,直到要插入的位置的记录移后一位。

二分插入排序是稳定的,平均时间O(n2)

void binsort(ref int[] data1)

1、二分法查找插入位置
  如果R[i]<R[m]成立,那右指针就要向左移动中间指针一位,否则,左指针要向左移动中间指针一位。反复查找,直到左指针大于右指针时停止。
2、后移,有点迷惑,什么时候需要后移呢?有哪些记录需要移动呢?
  虽然我们很清楚的知道,我们需要后移那些排序码大于R[i]的记录,但难免会问自己这样几个问题。其实它相当于需要移动从i-1到左指针的记录。
3、插入
  由1中得到的左指针其实就是元素要插入的位置。

4、算法

{

int left,right,num;

int middle,j;

for( int i = 1;i < data1.Length;i++)

{

// 准备

left = 0;

right = i-1;

num = data1[i];

// 二分法查找插入位置

while( right >= left)

{

// 指向已排序好的中间位置

middle = ( left + right ) / 2;

if( num < data1[middle] )

// 插入的元素在右区间

right = middle-1; 

else

// 插入的元素在左区间

left = middle+1;

}

// 后移排序码大于R[i]的记录

for( j = i-1;j >= left;j-- )

{

data1[j+1] = data1[j];

}

// 插入

data1[left] = num;

}

// 插入的元素在左区间

left = middle+1;

}

// 后移排序码大于R[i]的记录

for( j = i-1;j >= left;j-- )

{

data1[j+1] = data1[j];

}

// 插入

data1[left] = num;

}

iOS 排序算法总结、二分法查找的更多相关文章

  1. php排序算法及二分法查找

    插入排序 思想:将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表.即:先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序为止. 要点:设立 ...

  2. php常用的排序算法与二分法查找

    一 : 归并排序 将两个的有序数列合并成一个有序数列,我们称之为"归并".归并排序(Merge Sort)就是利用归并思想对数列进行排序.根据具体的实现,归并排序包括"从 ...

  3. Java实现四大基本排序算法和二分查找

    Java 基本排序算法 二分查找法 二分查找也称为折半查找,是指当每次查询时,将数据分为前后两部分,再用中值和待搜索的值进行比较,如果搜索的值大于中值,则使用同样的方式(二分法)向后搜索,反之则向前搜 ...

  4. 查找算法:二分法查找及其python实现案例

    承接上一篇:查找:顺序查找与二分法查找,将二分法更多详细的python实现解题写下笔记. 简单方法 ''' 二分法查找在列表中的用户输入值,返回index 三种情况跳出循环体: LR相邻 LR位置重合 ...

  5. python的算法:二分法查找(1)

    1.什么是二分法查找: 1.从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束: 2.如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从 ...

  6. python的算法:二分法查找(2)--bisect模块

    Python 有一个 bisect 模块,用于维护有序列表.bisect 模块实现了一个算法用于插入元素到有序列表.在一些情况下,这比反复排序列表或构造一个大的列表再排序的效率更高.Bisect 是二 ...

  7. java se系列(四) 函数、数组、排序算法、二分法、二维数组

    1 函数 1.1  数的概述 发现不断进行加法运算,为了提高代码的复用性,就把该功能独立封装成一段独立的小程序,当下次需要执行加法运算的时候,就可以直接调用这个段小程序即可,那么这种封装形形式的具体表 ...

  8. iOS常见算法(二分法 冒泡 选择 快排)

    二分法: 平均时间复杂度:O(log2n) int halfFuntion(int a[], int length, int number)  { int start = 0; int end = l ...

  9. IOS 排序算法

    /** * @brief 冒泡排序法 * * @param arr 需要排序的数组 */ -(void)BubbleSort:(NSMutableArray *)arr { // 取第一个与其邻接的对 ...

随机推荐

  1. css3 实现圆角边框的border-radius属性和实现阴影效果的box-shadow属性

    首先我要介绍的是border-radius属性,它的作用是实现圆角边框,其中border-radius:20px;表示,一个’体‘四个角都圆滑20px,其值如果为100px那么圆角度则为最高,如果是正 ...

  2. CentOS 5.5 虚拟机安装 VirtualBox 客户端增强功能

    .启动安装在 VirtualBox 中的 CentOS 5.5 虚拟机,点击“设备” => “安装增强功能”.这个时候你就可以看到有一个“光盘”已经挂载到 CentOS 5.5 的桌面上了.它包 ...

  3. poj 1201 Intervals 解题报告

    Intervals Time Limit: 2000MS   Memory Limit: 65536KB   64bit IO Format: %lld & %llu Submit Statu ...

  4. HBase入门基础教程之单机模式与伪分布式模式安装(转)

    原文链接:HBase入门基础教程 在本篇文章中,我们将介绍Hbase的单机模式安装与伪分布式的安装方式,以及通过浏览器查看Hbase的用户界面.搭建HBase伪分布式环境的前提是我们已经搭建好了Had ...

  5. Java输入输出处理技术2

    7.从键盘输入 从键盘输入一行字符,并显示到屏幕上. package io; import java.io.*; public class ReadAndWrite { public static v ...

  6. scala编程第17章学习笔记(2)——集和映射

    默认情况下在使用“Set”或“Map”的时候,获得的都是不可变对象.如果需要的是可变版本,需要先写明引用. 如果同一个源文件中既要用到可变版本,也要用到不可变版本的集合或映射,方法之一是引用包含了可变 ...

  7. nth-digit

    https://leetcode.com/problems/nth-digit/ public class Solution { public int findNthDigit(int n) { in ...

  8. 基于zabbix的Redis、Sentinel、Slave多实例自动发现监控

    约定 保证whereis redis-cli 能够正确返回redis-cli程序的路径 保证 redis的配置文件在模板宏{$REDIS_SERVER_CONFIG_PATH}的路径,并且后缀名 为. ...

  9. Flatten Binary Tree to Linked List leetcode java

    题目: Given a binary tree, flatten it to a linked list in-place. For example, Given 1 / \ 2 5 / \ \ 3 ...

  10. IOS UITableView多选删除功能

    UITbableView作为列表展示信息,除了展示的功能,有时还会用到删除,比如购物车.收藏列表等. 单行删除功能可以直接使用系统自带的删除功能,当横向轻扫cell时,右侧出现红色的删除按钮,点击删除 ...