用冒泡排序的方法模擬實現qsort函數

分析:

用冒泡排序的方法實現快速排序主要是用回調函數的知識,我們知道庫函數中qsort的函數原型是:

 

void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );

函數原型中qsort函數有四個參數,分別爲

base:是指目標數組的開始位置,可以理解爲數組首元素的地址;

num:是指數組中元素的個數;

width:是指數組中每個元素的類型的大小;

compare:是一個函數指針,是一個比較函數,它的返回值是int,通過它來判斷要比較的元素的類型;

下面是使用qsort函數例子:

#include<stdio.h>

#include<stdlib.h>

int int_cmp(const void *elem1, const void *elem2)

{

return *(int *)elem1 - *(int *)elem2;

}

int str_cmp(const void *elem1, const void *elem2)

{

return (char *)*(int *)elem1 - (char *)*(int *)elem2;

}

int main()

{

int arr[] = { 1, 5, 4, 3, 8, 7, 9, 5, 3, 4, 0 };

int size = sizeof(arr) / sizeof(arr[0]);

int i = 0;

qsort(arr, size, sizeof(int), int_cmp);

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

{

printf("%d ", arr[i]);

}

system("pause");

return 0;

}

wKioL1ZkYMnig0RQAAAZHwep5rM304.png

 我們也可以排序字符串

int main()

{

 char *arr[] = { "ddd","cccc","aaaa","bbbb" };

 int size = sizeof(arr) / sizeof(arr[0]);

 int i = 0;

 qsort(arr, size, sizeof(char *), str_cmp);

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

 {

  printf("%s ", arr[i]);

 }

 system("pause");

 return 0;

}

wKioL1ZkYySTSpmNAAAS_Cht9sE603.png

 

qsort可以實現多種類型的排序,我們可以模擬實現它。

要實現它我們要注意以下幾點:

  1. 要實現這個函數我們首先要有比較函數,用來比較兩個元素大小,判斷返回值的大小來確定是否要交換兩個元素。比較函數應設計爲返回值int,參數爲void * 類型的指針,因爲我們要實現多種類型的元素的排序。

  2. 還要一個交換函數,當兩元素滿足交換條件是交換它們。交換函數的類型應該爲返回值爲void,參數爲兩個char *類型指針(元素類型不同),還有一個是元素類型的大小(字節)。交換時應該以字節爲單位交換。

以下是我的實現方法:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int struct_cmp(const void *elem1, const void *elem2)   //比較結構體元素大小
{
return (*(stu *)elem1).score - (*(stu *)elem2).score; 
//將void*強制類型轉換爲結構體指針並對它解引用訪問成員score
}
int int_cmp(const void *elem1, const void *elem2)  //比較整型元素大小
{
return *(int *)elem1 - *(int *)elem2;
//將void*強制類型轉換爲整型指針並對它解引用
}
int str_cmp(const void *elem1, const void *elem2) //比較字符串大小
{
return strcmp((char *)*(int *)elem1 , (char *)*(int *)elem2);
//將void*強制類型轉換爲整型指針並對它解引用然後轉換爲char *類型的指針,用strcmp比較
}
void swap(char *elem1, char *elem2, int sz)    //實現兩個元素的交換
{
int i = 0;
char tmp = 0;
for (i = 0; i < sz; i++)  //一字節爲單位交換
{
tmp = *(elem1 + i);
*(elem1 + i) = *(elem2 + i);
*(elem2 + i) = tmp;
}
}
void bubble(void *base, int num, int width, int(*compare)(const void *elem1, const void *elem2))
{
int i = 0;
int j = 0;
int flag = 0;  //優化冒泡排序
char *arr = (char *)base;
for (i = 0; i < num-1; i++)
{
flag = 0;
for (j = 0; j < num-1-i; j++)
{
if (compare(arr + j*width, arr + (j + 1)*width)>0)   //比較將元素大小,若返回值大於0,則交換
{
swap((char *)(arr + j*width), (char *)(arr + (j + 1)*width), width);  //交換兩個元素
flag = 1;
}
}
if (flag == 0)
break;
}
}
測試如下:
typedef struct S
{
char name[10];
float score;
}stu;
int main()
{
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
int size = sizeof(arr)/sizeof(arr[0]);
int i = 0;

bubble(arr, size, sizeof(int), int_cmp);

for (i = 0; i < size; i++)
{
printf("%d ", arr[i]);
}
system("pause");
return 0;
}
int main()
{
 char *arr[] = { "aaa", "dddd", "cccc", "bbbb" };
 int size = sizeof(arr) / sizeof(arr[0]);
 int i = 0;
 bubble(arr, size, sizeof(char *),str_cmp);
 for (i = 0; i < size; i++)
 {
 printf("%s ", arr[i]);
 }
 system("pause");
 return 0;
}

wKiom1ZkaNuS81yFAAAt8-2tmcM418.png 

int main()
{
stu arr[] = { { "圓圓", 98.0 }, { "冉冉", 97.0 }, { "天天", 96.0 }, { "雯雯", 99.0 } };
int size = sizeof(arr)/sizeof(arr[0]);
int i = 0;
bubble(arr, size, sizeof(stu), struct_cmp);
for (i = 0; i < size; i++)
{
printf("%s %f\n", arr[i].name,arr[i].score);
}
system("pause");
return 0;
}

 wKioL1ZkaYujD0hxAAAmLqsK8rE493.png

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章