首页 > 其他 > 详细

使用冒泡排序讲解函数指针

时间:2014-04-07 04:44:33      阅读:296      评论:0      收藏:0      [点我收藏+]

指针不光可以指向数组,整型变量等data objects, 在C里面,指针也可以指向函数,指向函数的

指针有很多种用处,下面举例说明。

 

思考下面的问题,你想实现一个函数可以对任意数据类型进行排序,比如说,字符串,整数,浮点

数,甚至是结构体。具体的算法都用一样的,可以是冒泡排序,当然也可以是更复杂一些的算法,

比如 shell 或者快速排序。 为了演示,我们在这里使用简单的冒泡排序。

 

Sedgewick 有描述过怎样用C语言来实现冒泡排序,假设我们把函数名叫bubble(), 它可以是这个样

子的。 bubble1.c,

#include <stdio.h>

int arr[10] = { 3, 6, 1, 2, 3, 8, 4, 1, 7, 2};

void bubble(int a[], int N);

int main(void)
{
    int i;
    putchar(‘\n‘);
    for (i = 0; i < 10; i++)
    {
        printf("%d ", arr[i]);
    }
    bubble(arr, 10);
    putchar(‘\n‘);
    
    for (i = 0; i < 10; i++)
    {
        printf("%d ", arr[i]);
    }
    system("pause");
    return 0;
}
void bubble(int a[], int N)
{
     int i, j, t;
     for (i = N-1; i >= 0; i--)
     {
         for (j = 1; j <= i; j++)
         {
             if (a[j-1] > a[j])
             {
                        t = a[j -1];
                        a[j-1] = a[j];
                        a[j] = t;
             }
         }
     }
}

 

冒泡排序是一种比较简单的排序,这种算法扫描从第二到到最后一个,使用每一个元素和它之前的

那个元素比,如果前一个比当前元素要大,那么交换它们,这样,比较大的那一个就越来越靠近

数组的末尾,第一轮循环结束,最大的那个数将会移动到数组的末尾,下一轮循环将把第二大的

数列在最大的那个数前面,这样重复(元素个数减1)次,就会得到一个有序数组。

 

这里我们的函数有很大的局限性,只能比较整型数组里面的数据,为了能够比较任意类型,我们

先把比较这个过程从bubble()中拿出来,程序是这个样子的。

/* Separating the comparison function */
#include <stdio.h>
int arr[10] = { 3, 6, 1, 2, 3, 8, 4, 1, 7, 2};

void bubble(int a[], int N);
int compare(int m, int n);

int main(void)
{
    int i;
    putchar(‘\n‘);
    
    for (i = 0; i < 10; i++)
    {
        printf("%d ", arr[i]);
    }
    bubble(arr,10);
    putchar(‘\n‘);
    
    for (i = 0; i < 10; i++)
    {
        printf("%d ", arr[i]);
    }
    system("pause");
    return 0;
}

void bubble(int a[], int N)
{
     int i, j, t;
     for (i = N-1; i >= 0; i--)
     {
         for (j = 1; j <= i; j++)
         {
             if (compare(a[j-1], a[j]))
             {
                   t = a[j-1];
                   a[j-1] = a[j];
                   a[j] = t;
             }
         }
         
     }
}  

int compare(int m, int n)
{
    return (m > n);
}  


 

如果我们的目的是可以排任意类型的数据,有一种搞法是这样的,使用void 指针,而不使用整型

数据类型,作为这个方向的开始,我们对上面函数作一些简答的修改,这里我们将指针指整型数据。

#include <stdio.h>
int arr[10] = { 3, 6, 1, 2, 3, 8, 4, 1, 7, 2 };

void bubble(int *p, int N);
int compare(int *m, int *n);

int main(void)
{
    int i;
    putchar(‘\n‘);
    
    for (i = 0; i < 10; i++)
    {
        printf("%d ", arr[i]);
    }
    bubble(arr, 10);
    putchar(‘\n‘);
    
    for (i = 0; i < 10; i++)
    {
        printf("%d ", arr[i]);
    }
    system("pause");
    return 0;
}

void bubble(int *p, int N)
{
     int i, j, t;
     for (i = N-1; i >= 0; i--)
     {
         for (j = 1; j <= i; j++)
         {
             if (compare(&p[j-1], &p[j]))
             {
                 t = p[j-1];
                 p[j-1] = p[j];
                 p[j] = t;
             }
         }
         
     }
}

int compare(int *m, int *n)
{
    return (*m > *n);
}


注意我们修改到我地方,这里我们向bubble() 传递了一个指向integer的指针,下一步里,我们

将使用指向void 类型的指针,这样函数对数据类型变得更加的不敏感。

#include <stdio.h>
#include <stdio.h>

int arr[10] = {3, 6, 1, 2, 4, 8, 4, 1, 7, 2};

void bubble(int *p, int N);
int compare(void *m, void *n);

int main(void)
{
    int i;
    putchar(‘\n‘);
    
    for (i = 0; i < 10; i++)
    {
        printf("%d ", arr[i]);
    }
    bubble(arr, 10);
    putchar(‘\n‘);
    
    for (i = 0; i < 10; i++)
    {
        printf("%d ", arr[i]);
    }
    system("pause");
    return 0;
}

void bubble(int *p, int N)
{
     int i, j, t;
     for (i = N-1; i >= 0; i--)
     {
         for (j = 1; j <= i; j++)
         {
             if (compare((void *)&p[j-1], (void *) &p[j]))
             {
                  t = p[j - 1];
                  p[j-1] = p[j];
                  p[j] = t;
             }
         }
     }
     
}

int compare(void *m, void *n)
{
    int *m1, *n1;
    m1 = (int *)m;
    n1 = (int *)n;
    return (*m1 > *n1);
}
我们知道,数据的名字是一个指向其第一个元素(在数据段)地址的指针,同样的道理,函数名将指向函数代码
段的开始的地址。
 
指向函数的指针必须和函数参数的类型,个数以及返回值匹配,在这里我们这样定义
我们的函数指针:
int (*fptr)(const void *p1, const void *p2);


注意不能写成这样:

int *fptr(const void *p1, const void *p2);

如果写成这样,它的意思是给出了一个函数原型,它将返回一个指向int 的指针。这是因为

在C语言中括号() 比  * 的优先级要高。在* fptr  打个括号表示我们声明了一个函数指针。

这里我们修改一下bubble()的声明,增加第四个参数,一个指向合适类型的函数指针。

它的函数原型将变成这个样子:

void bubble(void *p, int width, int N, int (*fptr)(const void *, const void *));


当我们调用bubble的时候,将我们希望使用的比较函数名插进去。下面程序将会阐明这样方法的实现。

#include <stdio.h>
#include <string.h>

#define MAX_BUF 256

long arr[10] = {3, 6, 1, 2, 3, 8, 4, 1, 7, 2};
char arr2[5][20] = { " Mickey Mouse",
                     " Donald Duck",
                     " Minnie Mouse",
                     " Goofy",
                     " Ted Jensen" };
                     
void bubble(void *p, int width, int n,
            int (*fptr)(const void *, const void *));
int compare_string(const void *m, const void *n);
int  compare_long(const void *m, const void *n);                     
int main(void)
{
    int i;
    puts("\nBefore Sorting:\n");
    
    for (i = 0; i < 10; i++)     /* show the long ints */
    {
        printf("%ld ", arr[i]);
    }
    puts("\n");
    
    for (i = 0; i < 5; i++)
    {
        printf("%s\n", arr2[i]);      /* show the strings */
    }
    bubble(arr, 4, 10, compare_long);   /* sort the longs */
    bubble(arr2, 20, 5, compare_string);   /* sort the strings */
    puts("\n\nAfter Sorting:\n");
    
    for (i = 0; i < 10; i++)
    {
        printf("%d ", arr[i]);
    }
    puts("\n");
    
    for (i = 0; i < 5; i++)     /* show the sorted strings */
    {
        printf("%s\n", arr2[i]);
    }
    system("pause");
    
    return 0;
}

void bubble(void *p, int width, int N, 
            int (*fptr)(const void *, const void *))
{
            int i, j, k;
            unsigned char buf[MAX_BUF];
            unsigned char *bp = p;
            
            for (i = N - 1; i >= 0; i--)
            {
                for (j = 1; j <= i; j++)
                {
                    k =fptr((void *)(bp + width*(j-1)), (void *)(bp + j *width));
                }
                if (k > 0)
                {
                      memcpy(buf, bp + width*(j-1), width);
                      memcpy(bp + width*(j-1), bp + j*width, width);
                      memcpy(bp + j*width, buf, width);
                }
            }
}

int compare_string(const void *m, const void *n)
{
    char *m1 = (char *)m;
    char *n1 = (char *)n;
    return (strcmp(m1,n1));
}

int compare_long(const void *m, const void *n)
{
    long *m1, *n1;
    m1 = (long *)m;
    n1 = (long *) n;
    return (*m1 > *n1);    
}



  

使用冒泡排序讲解函数指针,布布扣,bubuko.com

使用冒泡排序讲解函数指针

原文:http://blog.csdn.net/robinsongsog/article/details/23062123

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!