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

来源:互联网 发布:e4a连接数据库 编辑:程序博客网 时间:2024/06/06 17:02

指针不光可以指向数组,整型变量等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 256long 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);    }



  

1 0
原创粉丝点击