try it, then you know it____________just do it , as love easily fade.

一次只有一个目标,步子迈小些,抑制一次实现所有功能的冲动。 过程如何结果就如何,行动是欢喜的,不管是兴奋还是沮丧的情绪都对结果无益。贵在持之以恒

导航

排序算法 1

直观的视频http://www.cnblogs.com/wangfupeng1988/archive/2011/12/26/2302216.html

1,冒泡排序

——冒泡,每一次最大的值升到最后面,像水泡升到了水面,冒出来了,不再位于水里,不再需要比较,它已经确定了,独立了。

每次从最前面开始比较相邻的两个数,如果前面的大于后面的则交换,直到末尾最后两个,结束后末尾为最大的数。

除去已经找到的最大数,继续从最前开始,两相邻数比较,直到此次数值序列的末尾。

重复以上过程,直到最后一次只有两个数值需要比较。

//the first circle , from  0,1 to ,count-2,cout-1
//the last circle, at 0,1

对每一次的数值序列,记录其是否发生了交换,如果没有,则不需要再进行下一次的循环。

void exchange(uchar * a, uchar *b)
{
    uchar temp;
    temp = *a;
    *a = *b;
    *b = temp;
}
//bubble sorting
int bubbleSort(int *a, int n)
{
    int i,j;
    int sentinel;  //to signal if exchange happen last run
    for(j = n - 1; j >= 1 && sentinel; j--) 
    {
        sentinel = 0;
        for(i = 0; i<= j - 1; i++)
        {
            if(a[i] > a[i + 1])
            {
                swap(&a[i], &a[i + 1]);
                sentinel = 1;
            }
        }
    }
}

 

2,插入排序

--和冒泡排序逻辑伤相反,冒泡是一次找一个最大值,是个体优先,插入呢,是保证我的序列始终是整齐的,每次放入一个数值到我的序列中。

第一次整齐的序列只有1个数,把相邻的下一个数与这个数相比较,放入合适的位置

下一次,对于排好的序列,再加入下一个数,从序列末尾开始向前依次进行比较,遇到比它大得则交换,遇到比它小的,停止这一次的比较。

重复以上过程,直到最后一次插入最后一个数。

//想到初中时的推理证明题,证明无穷大的情况,从1开始证明, 然后证明n时成立,推导出无穷大时成立。

void insertSort(int *a, int n)
{
    //1st:a[1] into a[0]
    //2ed:a[n - 1] into a[0]....a[n-2]
    int i, j;
    int key;
    for(j = 1; j <= n - 1; j++)
    {
        key = a[j];
        for(i = j; i >= 1; i--)
        {
            if(a[i - 1] > key)
            {
                a[i] = a[i - 1];
            }
            else
                break;
        }
        a[i] = key;
    }
}

 

3,快速排序

从队列中取一个基数,例如第一个数,其余数依次和这个数比较,比它大的放右边,小的放左边。这一次循环确定了这个基数的排列位置。

对于基数左边和右边的子数列,各自取基数,同第一次循环一样把各个数放基数的两边。

重复以上操作,直到最后一次子序列只有两个数。

----快速排序的优化              http://i.youku.com/u/UMzU2MjI1NzQ0

--小型数组数据的优化。eg,待整理数组个数小于7时,直接用插入排序。

--对于基准值的选取进行优化。讲队列头,尾,中,三个数排序,取中位置的值作为基准

--将递归优化为尾递归。见归并排序。

void quickSort(uchar a[], uchar low, uchar high)
{
    uchar i, j;
    uchar key;
    if(low >= high)
        return;
    key = a[low];
    i = low;
    j = high;
    while(j>i)
    {
        while(j>i)      //end at j = i;
        {
            if(a[j] < key)
            {
                a[i] = a[j];    //j is hold for key
                break;
            }
            j--;        //positon to compare
        }

        while(i<j)      //i+1 is the one to compare
        {
            i++;        //positon to compare
            if(a[i] > key)
            {
                a[j] = a[i]; //i is now hold for key
                break;
            }
        }
        if(j > 0 )  //0-1 should be avoided
            j--; //positon to comparte
    }
    a[i] = key;
    if(i-1 >= 0)        //0-1 should be avoided
        quickSort(a, low, i-1);
    quickSort(a, i+1, high);
}
void quickSort3(uchar a[], uchar low, uchar high)
{
    uchar i, j;
    uchar key;
    if(low >= high)
        return;
    key = a[low];
    i = low;
    j = high;
    while(j>i)
    {
        while(j>i && a[j] >= key)
        {
            j--;        //positon to compare
        }

        if(i!=j)
        {
            a[i]= a[j];//j is hold for key
            i++;       //this step together with if condition can be omitted
        }

        while(i<j && a[i] <= key)         
        {
            i++;        //positon to compare
        }
        if(i!=j )
        {
            a[j] = a[i];//i is now hold for key
            j--;     //this step together with if condition can be omitted 
        }
    }
    a[i] = key;
    if(i-1 >= 0)        //0-1 should be avoided
        quickSort3(a, low, i-1);
    quickSort3(a, i+1, high);
}

第二个逻辑清楚,不容易出错。

void quickSortInteration(int *a, int low, int high)
{
    int i,j;
    int key;

    if(low >= high) return;

key
= a[low]; //set a[low] as key. a[low] is empty now. i = low; //a[i] is empty, wait for date placing j = high; while(i < j) { while( key < a[j] && i < j ) { j--; } a[i] = a[j]; //a[j] is empty,waiting for date placing while( key >= a[i] && i < j ) { i++; } a[j] = a[i]; } a[i] = key; if(i > 1) { quickSortInteration(a, low, i - 1); } quickSortInteration(a, i + 1, high); } //quickSort: sort a[0]..a[n-1] into increasing order void quickSortMy(int *a, int n) { quickSortInteration(a, 0, n -1); }

 

 //其实怎样想都可以,只要能实现就行,唯一可以用思维的地方,总要给个出路。

4,选择排序

 选择排序和冒泡排序,一个从没排好的数列里找最大的,一个从没排好的数列里找最小的。选择排序就是选择最小的,一个个排。还不如叫沉泡排序呢。.下面的程序是官方的程序,虽然我本能倾向于程序该和冒泡程序类似的那种,自我开解下要是都一样就没意思了,所以选择官方这种有自己特色的选择排序。

void selectSort(int *a, int n)
{
    //1st get a[0] from a[0]...a[n-1]
    //last get a[n-2] from a[n-2], a[n-1]
    int i,j;
    int min;
    for(i = 0; i <= n - 2; i++)
    {
        min = i;
        for(j = i + 1;j <= n - 1;j++)
        {
            if(a[min] > a[j])
            {
                min = j;
            }
        }
        if(min != i)
        {
            swap(&a[min],&a[i]);
        }
    }
}
 

5,归并排序

普通话不标准总觉得别扭,不过讲得还行 http://v.youku.com/v_show/id_XNjg1NTQzNTg4.html

---迭代是要用利用已经算出来的一个值去计算下一个值,从远到近,一步步接近答案。递归是要解决的规模逐渐变小。

---递归就是自己调用自己,其运作包括两个过程,先拆后合。递归需要要结束条件。

先递推:将复杂问题简单化。eg,一个数列拆成左右两个部分,各部分再拆成左右两个部分,一直拆下去,直到各部分只剩下一个值为止。再归并:在获得最简单的情况后,逐次返回,得到复杂的解。

---递归的缺点,每进行一次,就要占用一块堆栈空间,容易造成堆栈的溢出。

---尾递归。函数中递归形式的调用出现在末尾。编译器会覆盖当前用的栈空间,而不占用新的占空间。所以只要有可能,使用递归时写成尾递归的形式。

//merge: merge two sorted array
void merge(int *a, int *b, int size_a, int size_b)
{
    int i,j,k;
    int size_buf = size_a + size_b;
    int *buf = (int *)malloc(sizeof(int) * size_buf);
    if(buf == NULL)
    {
        printf("space alloacted fail");
        return;
    }
    i = 0;
    j = 0;
    k = 0;

    while(i <= size_a - 1 && j <= size_b)
    {
        while(i <= size_a - 1 && a[i] <= b[j])  //store from a[i]
        {
            buf[k++] = a[i++];
        }
        while(j <= size_b - 1 && b[j] <= a[i])  //store from b[i]
        {
             buf[k++] = b[j++];
        }
        while(i >= size_a && j <= size_b - 1)   //a passed, store b
        {
            buf[k++] = b[j++];
        }
        while(j >= size_b  && i <= size_a - 1)  //b passed, store a
        {
            buf[k++] = a[i++];
        }
    }
    for(i = 0; i <= size_buf - 1; i++ )
    {
        a[i] = buf[i];
    }

    free(buf);
}

6,希尔排序

插入排序一般而言是低效的,因为一次只能将数据移动一位(//所以快速排序移动的位数最多效率最高吗),对于已经排好的序列,插入排序的效率较高。基于插入排序的特性,产生了更为高效的希尔排序。

就是再进行插入排序之前,对序列先进行一番调整,相隔远得先调一下。取一数值作为步长,将数据分成几个区间,对应值两两相比,再将步长缩小得到更小的区间,从前到后各区间对应位置的值相互比较。最后一次每个区间只剩一个数,就和插入排序一样了。迭代的过程。

void  shellSort(uchar a[], uchar n)
{
    uchar step ;
    uchar i,j,k;
    for(step=n/2;step>0;step/=2)    //step is half decreased here.
    {
        for(k = 0;k <= step-1;k++)             //move to the next pos
        {
            for(j = k+step;j <= n-1;j += step)   //compare the values at the same pos
            {
                for(i = j;i >= step;i -= step)   // i >= k + step is also ok,but confusing
                {
                    if(a[i-step] > a[i])
                        exchange(&a[i],&a[i-step]);
                    else
                        break;
                }
            }
        }
    }
}

7, 堆排序

//堆是挺漂亮的结构。

—— 完全二叉树两个条件,n层二叉树

1,from 1 layer to n-1 layer,with max number

2, at n layer, from left to right continuously

——二叉树成为大顶堆的两个条件:1, ki>=k2i   2,ki>=k(2i+1). 1<= i<=n/2.

——堆排序,

1,将大顶堆根节点和末尾节点交换,

2,除去当前末尾最大的数,剩下的数再调整为大顶堆,

3,重复1,2

//adding left>right for handling,not necessary.
void handleChild(uchar a[], uchar n,uchar childIndex) { uchar k;
for(k = childIndex;k<=n/2 ;k*=2) { if(a[k] < a[2*k]) swap(&a[k],&a[2*k]); } } void heapSort(uchar a[], uchar n) { uchar i,j; uchar childIndex; uchar heap[i+1];for(i=0;i<=n-1;i++) { heap[i+1] = a[i]; } //repeat the progress for(j=n;j>=2;j--) { //build a big heap.2 conditions:1st,ki>=k2i,2ed,ki>=k2i+1 for(i=j/2;i>=1;i--) { childIndex = 2*i; //adjust to get right > left if(childIndex+1 <= j && heap[childIndex] < heap[childIndex+1]) { swap(&heap[childIndex],&heap[childIndex+1]); handleChild(heap,j,childIndex+1); } //compare father with right if(heap[i] < heap[childIndex]) { swap(&heap[i],&heap[childIndex]); handleChild(heap,j,childIndex); } } //place the root at the end swap(&heap[1],&heap[j]); } printf("%d\n..",count); //get the result for(i=1;i<=n;i++) { a[i-1] = heap[i]; } }

 

uchar count=0;
void adjustNode(uchar heap[], uchar i,uchar n)
{
    uchar j;
    uchar temp = heap[i];   //store node date.

        for(j=2*i;j<=n;j*=2)             //j is left child
        {
            count++;
            if(j+1<=n && heap[j]<heap[j+1])
            {
                j++;                    //j move to right child
            }
            if(temp>heap[j])
            {
                break;
            }
            heap[i]=heap[j];
            i = j;       //current node.
        }
        heap[i] = temp;
}
void heapSort(uchar a[],uchar n)
{
    uchar i;
    uchar heap[n+1];    //define a heap

    //build a tree
    heap[0]=0XFF;
    for(i=0;i<=n-1;i++)
    {
        heap[i+1]=a[i];
    }
    //adjust node to build a heap
    for(i=n/2;i>=1;i--)
    {
        adjustNode(heap,i,n);
    }
    //exchange the root node with the last node.adjust the rest date to heap,
    for(i=n;i>=2;i--)
    {
        swap(&heap[1],&heap[i]);  //the largest is placed at end.
        adjustNode(heap,1,i-1);
    }
    //return the dates
    for(i=0;i<=n-1;i++)
    {
        a[i]=heap[i+1];
    }
}

 ______test function

 

//scaffolding test:1,sorted;2,values consistent
//sorted
int sorted(int *a, int n)
{
    int i;
    for(i = 0; i <= n - 2; i++)
    {
        if(a[i] > a[i + 1])
        {
            return 0;
        }
    }
    return 1;
}
//conform: if conform, return 1;else return 0
int conform(int *a, int *b, int n)
{
    int buf[n];
    int i,j;
    i = n;
    while(i--)
    {
        buf[i] = 0;
    }
    for(j = 0; j <= n - 1;j++)
    {
        for(i = 0; i <= n - 1;i++)
        {
            if(b[j] == a[i] && buf[i] == 0)
            {
                buf[i] = 1;
                break;
            }
        }
        if(i >= n)
            return 0;
    }
    for(i = 0; i <= n -1; i++)
    {
        if(0 == buf[i])
            return 0;
    }
    return 1;
}

 

//memcpy,for scaffolding test. the original array need to be stored
void memcpyMy( void *destination, const void *source, int n)
{

    char *dest = destination;
    const char *src = source;

    while(n--)
    {
       *dest++ = *src++;        //unitary operator calcul from right to left
    }
}
int vGenerateRandomValue(int max)
{
    int r;
    //srand( (unsigned int)time(0) );
    r = rand() % max + 1;   // return 1 - max
    return r;
}
#define MAXN 10
int main()
{
    int x[MAXN];
    int buffer[MAXN];
    int i;
    int n;
    int max = 100;
for(n = 1; n <= MAXN ; n++)
    {
        printf("\n n= %d\n",n);
        for( i = 0; i <= n - 1; i++ )
        {
            x[i] = vGenerateRandomValue(max) - 1; //0 - 9
            printf(" %d", x[i]);
        }
        printf("\nsorted: \n");

        memcpyMy(buffer,x,n*sizeof(int));   //store original dates for later test

        mergeSort(x,n);

        for( i = 0; i <= n - 1; i++ )
        {
            printf(" %d", x[i]);
        }
        printf("\n");

        #define  s  sorted
        #define  c  conform
        assert(s(x, n));
        assert(c(x, buffer,n));
    }

    return 0;
}

 

posted on 2015-02-12 19:36  吾一  阅读(223)  评论(0编辑  收藏  举报