数据结构与算法--查找与排序

参考:https://blog.csdn.net/opera95/article/details/51217021


线性查找
二分查找
冒泡排序
插入排序
选择排序
快速排序
归并排序


1 线性查找

线性查找,又称为顺序查找,是指在所有给定的值中从一端开始逐个检查每个元素是否为要查找的对象,直到找到为止的过程。

##逐个查找要查找的对象

#include <stdio.h>
typedef char DataType;
int mySearch(DataType *ts, int n, const DataType d) {
    for (int i = 0; i < n; i++)
        if (ts[i] == d)
            return i;
    return -1;
}
int main()
{
    char cs[6] = {'*','A','B','C','D','E'};
    printf("%d\n", mySearch(cs, 6, '*'));
    printf("%d\n", mySearch(cs, 6, 'A'));
    printf("%d\n", mySearch(cs, 6, 'D'));
    printf("%d\n", mySearch(cs, 6, 'C'));
}

2 二分查找

二分查找算法,又称折半搜索、二分搜索,是一种在有序数组中查找某一特定元素的搜索算法。

二分查找算法的查找过程是这样的。首先,要求待查找的数组是排好序的数组,我们假设数组是升序的,即从小到大排序。然后,将要查找的元素与数组的中间元素相对比,如果相等,则表示要查找的元素被找到了,并停止查找;如果要查找的元素小于数组的中间元素,则从数组中间元素开始到数组最后的元素都大于要查找的元素,也就不需要在其中查找了,只需要在数组中间元素到数组第一个元素之间查找;如果要查找的元素大于数组的中间元素,则从数组中间元素到数组第一个元素都小于要查找的元素,也就不需要在其中查找了,只需要在数组中间元素到数组最后的元素之间查找。二分查找算法在查找的过程中只需对比一次,就可以使待查找的对象个数减少一半。查找速度非常快,所以二分查找算法得到了广泛的应用。

步骤一:定义上下界

步骤二:确定中间点

步骤三:重新确定查找范围

步骤四:按新范围重新查找

typedef char DataType;
int mySearch(DataType *ts, int n, const DataType d) {
    int L = 0;
    int R = n - 1;
    while (L <= R) {
        int M = (L + R)/2;
        if (ts[M] == d) return M;
        if (ts[M] < d)
            L = M+1;
        else
            R = M - 1;
    }
    return -1;
}
int main()
{
    char cs[6] = {'*','A','B','C','D','E'};
    printf("%d\n", mySearch(cs, 6, '*'));
    printf("%d\n", mySearch(cs, 6, 'A'));
    printf("%d\n", mySearch(cs, 6, 'D'));
    printf("%d\n", mySearch(cs, 6, 'C'));
}

3 冒泡排序

冒泡排序是一种著名的排序方法。

冒泡排序的过程是这样的,首先,将待排序的数组中的第一个元素与第二个元素相对比,如果这两个元素的大小顺序不是我们要求的顺序,则将它们交换过来。然后,将待排序的数组中的第二个元素与第三个元素相对比,如果这两个元素的大小顺序也不是我们要求的顺序,则也将它们交换过来。下一步,是对比第三个元素与第四个元素,直至倒数第二个元素与最后一个元素相对比。这样一趟对比下来,小的数据元素会一点一点的往前放,而大的数据元素会一点一点的往后放。反复多趟的这样对比,直到所有数据都排好序为止。

步骤一:第一趟比较

步骤二:多趟比较,直至排好序

步骤三:设置标志,提高效率–定义一个布尔型变量,初始化为真,为真代表数组已经排好序了

typedef int DataType;
void bubble(DataType* a, int n) {
    for (int i = 0; i < n - 1; i++) {
        bool flag = true;
        for (int j = 0; j < n -  i - 1; j++) {
            if (a[j] > a[j + 1]) {
                DataType t = a[j];
                a[j] = a[j + 1];
                a[j + 1] = t;
                flag = false;
            }
        }
        if (flag) break;
    }
}
void print(DataType* a, int n) {
    for (int i = 0; i < n; i++)
        printf("%d ", a[i]);
    printf("\n");
}
int main() {
    int a[10] = {3, 2, 4, 5, 7, 8, 9, 1, 6, 0};
    bubble(a, 10);
    print(a, 10);
    
    return 0;
}

4 插入排序

插入排序算法是一种简单直观的排序算法。

插入排序的过程是这样的,首先,将待排序的数组分成两部分,一部分是已经排好序的部分,另一部分是未排好序的部分。在开始排序前,已排好序的部分只有一个数组元素,即数组的第一个元素;未排好序的部分是数组中除第一个元素外的其它所有元素。然后,将未排好序部分中的第一个数组元素,插入到已排序部分当中适当的位置,以保证已排序部分仍然是保持排序状态。此时,已排序部分就变成两个数组元素,而未排序部分的数组元素同时少了一个。依次类推,逐个从未排好序的部分拿出一个元素,插入到已排序部分当中适当的位置,直至数组按顺序排好为止。

步骤一:将未排序部分的第一个元素插入到已排序部分

步骤二:将所有未排序部分的元素插入到已排序部分

typedef int DataType;
void insert(DataType *a, int n) {
    for (int i = 1; i < n; i++) {
        //把选择的元素放在临时变量中
        DataType t = a[i];
        int j = 0;
        for (j = i; j > 0 && a[j - 1] > t; j--) {
            a[j] = a[j - 1];
        }
        a[j] = t;
    }
}
void print(DataType* a, int n) {
    for (int i = 0; i < n; i++)
        printf("%d ", a[i]);
    printf("\n");
}
int main() {
    int a[10] = {3, 2, 4, 5, 7, 8, 9, 1, 6, 0};
    insert(a, 10);
    print(a, 10);
    
    return 0;
}

5 选择排序

选择排序是一种简单直观的排序方法。

选择排序的过程是这样的,首先,在待排序的数组中找到一个最小的数组元素,将该最小数组元素与数组的第一个元素进行交换,这样交换之后,数组的第一个元素就变成了数组元素中的最小值。然后,再在待排序数组的剩余元素中找到一个最小的数组元素,将该最小数组元素与数组的第二个元素进行交换,这样交换之后,数组的第二个元素就变成了数组元素中的第二小的值。依次类推,直至数组按顺序排好为止。

步骤一:寻找数组中指定范围内的最小元素

步骤二:将最小元素与数组第一个位置的元素交换

步骤三:将数组剩余元素排序

typedef int DataType;
void selects(DataType *a, int n) {
    for (int i = 0; i < n - 1; i++) {
        int k = i; //这里认为k就是最小
        for (int j = i + 1; j < n; j++) {
            if (a[j] < a[k]) {
                k = j;
            }
        }
        if (k != i) {
            swap(a[k], a[i]);
        }
    }
}
void print(DataType* a, int n) {
    for (int i = 0; i < n; i++)
        printf("%d ", a[i]);
    printf("\n");
}
int main() {
    int a[10] = {3, 2, 4, 5, 7, 8, 9, 1, 6, 0};
    
    selects(a, 10);
    print(a, 10);
    return 0;
}

6 快速排序

快速排序算法是一种基于交换的排序,系统地交换反序的记录的偶对,直到不再有这样一来的偶对为止。它是对冒泡排序的一种改进。

快速排序的过程是这样的。首先,将待排序的数组从前向后和从后向前各取出一个元素进行对比交换,从而将待排序的数组分成两个部分,前一部分的所有元素都小于后一部分的所有元素,但前后两部分内部仍然是无序的状态。然后再将前一部分的所有元素从前向后和从后向前各取出一个元素进行对比交换,从而将前一部分的所有元素再分成两个部分,这两部分的前一部分的所有元素都小于后一部分的所有元素,依次类推,直到被分割的部分只有一个元素为止。下一步,再将后一部分的所有元素从前向后和从后向前各取出一个元素进行对比交换并分成两个部分。这样分到最后,数组将排好序。

步骤一:终止分组条件

步骤二:将数组分成两部分

步骤三:递归分组

typedef int DataType;
void qsorts(DataType *a, int n) {
    if(n <= 1) return;
    int L = 0;
    int R = n - 1;
    while (L < R) {
        //一次分组
        while (L < R && a[L] <= a[R]) R--;
        DataType t = a[L];
        a[L] = a[R];
        a[R] = t;
        while (L < R && a[L] <= a[R]) L++;
        t = a[L];
        a[L] = a[R];
        a[R] = t;
    }
    //继续左边分组
    qsorts(a, L);
    //继续右边分组
    qsorts(a + L + 1, n - L - 1);
}
void print(DataType* a, int n) {
    for (int i = 0; i < n; i++)
        printf("%d ", a[i]);
    printf("\n");
}
int main() {
    int a[10] = {3, 2, 4, 5, 7, 8, 9, 1, 6, 0};
    
    qsorts(a, 10);
    print(a, 10);
    
    return 0;
}

7 归并排序

归并排序是将两个已经排好序的序列合并成一个序列的操作。

归并排序的过程是这样的。首先,将待排序的数组中的元素从中间分为前后两部分。然后再将前一部分继续分成两部份,后一部分也继续分成两部分,依次类推,直到单个元素为止。最后两两按序合并,直到整个数组合并成一个有序数组为止。

步骤一:将数组分成前后两部分

步骤二:将前后两部分重新按序合并

#include<stdlib.h>
#include<stdio.h>
#define SIZE 8
void Merge(int sourceArr[],int startIndex,int midIndex,int endIndex)
{
    int start = startIndex;
    int i,j,k;
    int tempArr[SIZE];
    for(i=midIndex+1,j=startIndex;startIndex<=midIndex&&i<=endIndex;j++)
        if(sourceArr[startIndex]<=sourceArr[i])
            tempArr[j]=sourceArr[startIndex++];
        else
            tempArr[j]=sourceArr[i++];
    if(startIndex<=midIndex)
        for(k=0;k<=midIndex-startIndex;k++)
            tempArr[j+k]=sourceArr[startIndex+k];
    if(i<=endIndex)
        for(k=0;k<=endIndex-i;k++)
            tempArr[j+k]=sourceArr[i+k];
    for(i=start;i<=endIndex;i++)
        sourceArr[i]=tempArr[i];
}
//内部使用递归
void MergeSort(int sourceArr[],int startIndex,int endIndex)
{
    int midIndex;
    if(startIndex<endIndex)
    {
        midIndex=(startIndex+endIndex)/2;
        MergeSort(sourceArr,startIndex,midIndex);
        MergeSort(sourceArr,midIndex+1,endIndex);
        Merge(sourceArr,startIndex,midIndex,endIndex);
    }
}
//调用
int main(int argc,char * argv[])
{
    int a[SIZE] = {8,4,6,3,1,7,5,2};
    MergeSort(a,0,SIZE-1);
    for(int i=0;i<SIZE;i++)
        printf("%d ",a[i]);
    printf("\n");
    return 0;
}

    原文作者:查找算法
    原文地址: https://blog.csdn.net/qq_38096703/article/details/80343226
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞