zoukankan      html  css  js  c++  java
  • 排序算法 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 ..",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= %d
    ",n);
            for( i = 0; i <= n - 1; i++ )
            {
                x[i] = vGenerateRandomValue(max) - 1; //0 - 9
                printf(" %d", x[i]);
            }
            printf("
    sorted: 
    ");
    
            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("
    ");
    
            #define  s  sorted
            #define  c  conform
            assert(s(x, n));
            assert(c(x, buffer,n));
        }
    
        return 0;
    }
  • 相关阅读:
    Ethical Hacking
    Ethical Hacking
    Python Ethical Hacking
    Python Ethical Hacking
    Python Ethical Hacking
    食物链 POJ
    Wireless Network POJ
    Candies POJ
    畅通工程再续 HDU
    Jungle Roads HDU
  • 原文地址:https://www.cnblogs.com/aprilapril/p/4288816.html
Copyright © 2011-2022 走看看