码迷,mamicode.com
首页 > 编程语言 > 详细

八大排序

时间:2020-09-17 12:34:28      阅读:20      评论:0      收藏:0      [点我收藏+]

标签:item   gif   int   ++i   const   右值   简单   img   inf   

数据结构八大排序中的图解

1.排序的基本概念

2.交换类排序法

? 1-冒泡排序

技术图片

? 2-快速排序

技术图片

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

int stack[512];
int top = 0;

void init_stack()
{
    top = 0;
}
void push(int item)
{
    stack[top++] = item;
}

int pop(void)
{
    return stack[--top];
}

int is_empty(void)
{
    return top == 0;
}

//交换
void swap(int *a, int *b)
{
	int tmp;
	tmp = *a;
	*a = *b;
	*b = tmp;
}

//打印一个数组
void print_array(int *a, int len)
{
	int i;

	for (i = 0; i < len; i++)
	{
		printf("%5d", a[i]);
	}
	printf("\n");
}

//冒泡排序
void bubble_sort(int *v, int len)
{
	int i;
	int j;

	int is_change = 1;

	for (i = 0; is_change && i < len; i++)
	{
		is_change = 0;

		for (j = 0; j < len - 1 - i; j++)
		{
			if (v[j] > v[j + 1])
			{
				swap(v + j, v + j + 1);
				is_change = 1;
			}
		}
		// print_array(v, len);
	}

}

//递归实现快速排序
void quick_sort1(int *v, int left, int right)
{
    int key;
    int i;
    int j;

    if (left > right)
    {
        return;
    }

    key = v[left];
    i = left;
    j = right;

    //由小到大排序
    while(i < j)
    {    
        while ((i < j) && (v[j] >= key))
        {
            j--;
        }     
        
         while((i < j) && (v[i] <= key))
        {
            i++;
        }
        
        if (i < j)
        {
            swap(v + i, v + j);
        }

    }

    swap(v + i, v + left);
    
    quick_sort1(v, left, i - 1);      //左边
    quick_sort1(v, i + 1, right);     //右边
}

//以最右值为标准
int partition_right(int v[], int left, int right)
{
    int i = left;
    int j = right;
    int key = v[right];

    while (i < j)
    {   
        while ((i < j) && (v[i] <= key))
        {
            i++;
        }

        while ((i < j) && (v[j] >= key) )
        {
           j--;
        }

        if (i < j)
        {
            swap(v + i, v + j);
        }
    }

    swap(v + i, v + right);
   
    return i;
}

//以最左值为标准
int partition_left(int v[], int left, int right)
{
    int i = left;
    int j = right;
    int key = v[left];

    while (i < j)
    {  
        while ((i < j) && (v[j] >= key) )
        {
           j--;
        }

        while ((i < j) && (v[i] <= key))
        {
            i++;
        }

        if (i < j)
        {
            swap(v + i, v + j);
        }
    }

    swap(v + i, v + left);

    return i;
}

void quick_sort2(int *v, int left, int right)
{
    int i;

    if (left > right)
    {
        return;
    }

    i = partition_right(v, left, right);

    quick_sort2(v, left, i - 1);
    quick_sort2(v, i + 1, right);
}

#define push2(A, B)  push(B); push(A);

//迭代的方法实现快速排序
void quick_sort3(int *v, int left, int right)
{ 
    int i;
    init_stack(); 
    push2(left, right);

    while (!is_empty())
    {
        left = pop();
        right = pop(); 

        if (right <= left)
        {
            continue;
        } 
            
        i = partition_right(v, left, right);

        if (i - left > right - i)
        { 
            push2(left, i - 1); 
            push2(i + 1, right); 
        }
        else
        { 
            push2(i + 1, right); 
            push2(left, i - 1); 
        }
    }
}

int main(int argc, char const *argv[])
{
	int v[] = {14, 99, 65, 97, 73, 13, 18, 0, 55, 32, -11, 101, 999, -111, 11, -100, 100, 87, 987, 12, 14, -99, 66};
	int a[] = {14, 99, 65, 97, 73, 13, 18, 0, 55, 32, -11, 101, 999, -111, 11, -100, 100, 87, 987, 12, 14, -99, 66};

	int len = sizeof(v) / sizeof(v[0]);

	print_array(a, len);

	memcpy(a, v, sizeof(v));
	bubble_sort(a, len);
	print_array(a, len);
 
	memcpy(a, v, sizeof(v));
	quick_sort1(a, 0, len - 1);
	print_array(a, len);

	memcpy(a, v, sizeof(v));
	quick_sort2(a, 0, len - 1);
	print_array(a, len);

    memcpy(a, v, sizeof(v));
    quick_sort3(a, 0, len - 1);
    print_array(a, len);

	return 0;
}

◇递归排序

◇迭代排序

◇C语音qsort()函数

3.插入类排序法

?3-直接插入排序 (Straight Insertion Sort)

技术图片
技术图片
技术图片

?4-希尔排序(Shell Sort)

技术图片

技术图片

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

//交换
void swap(int *a, int *b)
{
	int tmp;
	tmp = *a;
	*a = *b;
	*b = tmp;
}

//打印一个数组
void print_array(int *a, int len)
{
	int i;

	for (i = 0; i < len; i++)
	{
		printf("%5d", a[i]);
	}
	printf("\n");
}


//直接插入排序
void insert_sort1(int *a, int len)
{
	int i;
	int j;
	int current_value;
	int pos;

	for (i = 1; i < len; i++)
	{
		current_value = a[i];

		//找到位置
		for (j = 0; j < i; j++)
		{
			if (current_value < a[j])
			{
				break;
			}
		}

		//如果在前面某个位置,插入,否则即为最大值,不用插入
		if (j < i)
		{
			pos = j;

			for (j = i; j > pos; j--)
			{
				a[j] = a[j - 1];
			}

			a[pos] = current_value;
		}

		//print_array(a, len);
	}
}

void insert_sort2(int *v, int len)
{
	int i;
    int j = 0;
    int current_value;

    for(i = 1; i < len; i++)
    {
        if(v[i] < v[i - 1])
        {
            current_value = v[i];

            for(j = i - 1; (j >= 0) && (v[j] > current_value); j--)
            {
                v[j + 1] = v[j] ;
            }

            v[j + 1] = current_value;
        }
        //print_array(a, len);
    }
}

//折半插入排序
void bin_insert_sort(int *a, int len)
{
	int i;
	int j;
	int current_value;
	int low;
	int high;
	int mid;

	for (i = 1; i < len; i++)
	{
		low = 0;
		high = i - 1;
		current_value = a[i];

		//找到位置
		while (low <= high)
		{
			mid = (low + high) / 2;

			if (current_value < a[mid])
			{
				high = mid - 1;
			}else
			{
				low = mid + 1;
			}
		}

		//二分法有时不是特别精准,需要校准
		if (current_value > a[mid])
		{
			mid = mid + 1;
		}

		//移动数据
		for (j = i; j > mid; j--)
		{
			a[j] = a[j - 1];
		}

		//插入数据
		a[mid] = current_value;

		//print_array(a, len);
	}
}

//简单希尔排序
void shell_sort1(int *v, int len)
{
	int gap;
	int i;
	int j;

	for (gap = len / 2; gap > 0; gap /= 2)
	{
		for (i = gap; i < len; i++)
		{
			for (j = i - gap; j >= 0; j -= gap)
			{
				if (v[j] < v[j + gap])
				{
					break;
				}

				swap(v + j, v + j + gap);
			}

		}
		//print_array(v, len);
	}
}

//常见希尔排序
void shell_sort2(int *v, int len)
{
    int j = 0 ;
    int i;
    int current_value;
    int gap = len;

    do
    {
        gap = gap / 3  + 1;

        for(i = gap; i < len; i++)
        {
            if(v[i] < v[i - gap])
            {
                current_value = v[i];

                for(j = i - gap;  (j >= 0) && (v[j] > current_value); j -= gap)
                {
                    v[j + gap] = v[j];
                }

                v[j + gap] = current_value;
            }
        }
    }while(gap > 1);
}

int main(int argc, char const *argv[])
{
	int v[] = {14, 99, 65, 97, 73, 13, 18, 0, 55, 32, -11, 101, 999,-111,11, -90, 87, -60, 81, -10, 12, -119, 911, 375};
	int a[] = {14, 99, 65, 97, 73, 13, 18, 0, 55, 32, -11, 101, 999,-111,11, -90, 87, -60, 81, -10, 12, -119, 911, 375};

	int len = sizeof(v) / sizeof(v[0]);

	print_array(a, len);

	memcpy(a, v, sizeof(v));
	insert_sort1(a, len);
	print_array(a, len);

	memcpy(a, v, sizeof(v));
	insert_sort2(a, len);
	print_array(a, len);


	memcpy(a, v, sizeof(v));
	bin_insert_sort(a, len);
	print_array(a, len);

	memcpy(a, v, sizeof(v));
	shell_sort1(a, len);
	print_array(a, len);

	memcpy(a, v, sizeof(v));
	shell_sort2(a, len);
	print_array(a, len);

	return 0;
}

4.选择类排序法

?5-简单选择排序(Simple Selection Sort)

技术图片
技术图片
技术图片

?6-堆排序(Heap Sort)

技术图片
技术图片

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

//交换
void swap(int *a, int *b)
{
	int tmp;
	tmp = *a;
	*a = *b;
	*b = tmp;
}

//打印一个数组
void print_array(int *a, int len)
{
	int i;

	for (i = 0; i < len; i++)
	{
		printf("%5d", a[i]);
	}
	printf("\n");
}

//选择一个数组中最小的数据
int select_min(int *v, int start, int end)
{
	int i;
	int min = v[start];
	int min_pos = start;

	for (i = start; i < end; i++)
	{
		if (min > v[i])
		{
			min = v[i];
			min_pos = i;
		}
	}

	return min_pos;
}

//简单选择排序
void simple_select_sort(int *v, int n)
{
	int i = 0;
	int min_pos;

	for (i = 0; i < n; i++)
	{
		min_pos = select_min(v, i, n);
		swap(v + i, v + min_pos);
	//	print_array(v, len);
	}
}

//大根堆进行调整
void adjust_heap(int *v, int start, int end)
{
    int root_value = v[start];
    int parent = start;
    int i;

    if (start == end)
    {
    	return;
    }

	//从节点start开始到end为止, 自上而下比较, 如果子女的值大于双亲,则子女上升,原来的双亲下落到
	//大子女的位置,这样逐层处理,将一个集合的局部调整为大根堆
    for (i = start * 2 + 1; i < end; i = i * 2 + 1)
    {
        //如果右边值大于左边值,指向右边
        if ((i + 1 < end) && (v[i] < v[i+1]))
        {
            i++;
        }

        if (root_value >= v[i])
        {
        	break;
        }
        else
        {
            v[parent] = v[i];
            parent = i;
        }
    }

    //put the value in the final position
    v[parent] = root_value;
}

//堆排序主要算法
void heap_sort(int v[], int  len)
{
	int i;

    //1.构建大根堆
    for (i = len / 2 - 1; i >= 0; i--)
    {
        //put the value in the final position
        adjust_heap(v, i, len);
    }

    //2.调整堆结构+交换堆顶元素与末尾元素
    for (i = len - 1; i > 0; i--)
    {
        //堆顶元素和末尾元素进行交换
        swap(v, v + i);

        adjust_heap(v, 0, i);//重新对堆进行调整
    }
}

int main(int argc, char const *argv[])
{
	int v[] = {14, 99, 65, 97, 73, 13, 18, 0, 55, 32, -11, 101, 999,-111,11, -90, 87, -60, 81, -10, 12, -119, 911, 375};
	int a[] = {14, 99, 65, 97, 73, 13, 18, 0, 55, 32, -11, 101, 999,-111,11, -90, 87, -60, 81, -10, 12, -119, 911, 375};
	
	int len = sizeof(v) / sizeof(v[0]);

	print_array(a, len);
	
	memcpy(a, v, sizeof(v));
	simple_select_sort(a, len);
	print_array(a, len);
	
	memcpy(a, v, sizeof(v));
	heap_sort(a, len);
	print_array(a, len);

	return 0;
}

5.归并排序法

?7-迭代法

?8-递归法

技术图片
技术图片

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

//交换
void swap(int *a, int *b)
{
	int tmp;
	tmp = *a;
	*a = *b;
	*b = tmp;
}

//打印一个数组
void print_array(int *a, int len)
{
	int i;

	for (i = 0; i < len; i++)
	{
		printf("%5d", a[i]);
	}
	printf("\n");
}

//二路一次归并过程的算法
//low为本次二路归并排序的第1有序区的第1个元素,i指向第1个元素, mid为第1有序区的最后1个元素
void merge(int *v, int *v_aux, int low, int mid, int high)
{
    //mid+1为第2有序区第1个元素,mid为第1有序区的最后1个元素
    int i = low;            //i 指向第 1 有序区的第 1 个元素
    int j = mid + 1;        //j 指向第 2 有序区的第 1 个元素,high 为第 2 有序区的最后一个元素
    int k = 0;              //设置临时数组的指示标志 k

    //顺序选取两个有序区的较小元素,存储到v_t数组中,因为是递增排序
    while(i <= mid && j <= high)
    {
        //较小的元素,存入v_t临时数组中
        if(v[i] <= v[j])
        {
             v_aux[k++] = v[i++];
        }else
        {
             v_aux[k++] = v[j++];
        }
    }

    //比完之后,假如第1个有序区仍有剩余,则直接全部复制到 v_t 数组
    while(i <= mid)
    {
        v_aux[k++] = v[i++];
    }

     //比完之后,假如第2个有序区还有剩余,则直接全部复制到 v_t 数组
    while(j <= high)
    {
        v_aux[k++] = v[j++];
    }

    //将排好序的序列,重存回到 list 中 low 到 high 区间
    for(i = low, k = 0; i <= high; i++, k++)
    {
        v[i] = v_aux[k];
    }
}


//递归实现二路归并排序(分治法的思想)
void merge_sort(int *v, int *v_aux ,int low, int high)
{
    //二路归并排序,分为二路
    int mid = (low + high) / 2;

    //终止条件,low >= high, 不是while,且不含等号,否则死循环
	if(low < high)
	{
		//递归过程,二路归并排序递归过程
		merge_sort(v, v_aux ,low, mid);
		merge_sort(v, v_aux ,mid + 1, high);
		//归并
		merge(v, v_aux, low, mid, high);
	}
}

int main(int argc, char const *argv[])
{
	int v[] = {14, 99, 65, 97, 73, 13, 18, 0, 55, 32, -11, 101, 999, -111, 11, -90, 87, -60, 81, -10, 12, -119, 911, 375};

	int len = sizeof(v) / sizeof(v[0]);
	int *v_aux = (int *)malloc(len * sizeof(int));
	if (v_aux ==  NULL)
	{
		printf("malloc failed\n");
		exit(1);
	}

	print_array(v, len);

	merge_sort(v, v_aux, 0, len - 1);
	print_array(v, len);

	free(v_aux);
	return 0;
}

6.基数排序法

技术图片

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

#define MAX_D   4                    //最大数是多少位
#define NUM_BUCKET 10                //定义桶的数目,这里是10进制

//交换
void swap(int *a, int *b)
{
    int tmp;
    tmp = *a;
    *a = *b;
    *b = tmp;
}

//打印一个数组
void print_array(int *a, int len)
{
    int i;

    for (i = 0; i < len; i++)
    {
        printf("%5d", a[i]);
    }
    printf("\n");
}


//求某一位上的数字 4321, 最高位时k为1
int get_m_digit(int x, int k)
{
    int r[MAX_D] = {1000, 100, 10, 1};

    #if 0
    int t = x;
    int i;

    if (k < 1 || k > MAX_D)
    {
        return -1;
    }

    for (i = 0; i < MAX_D - k; ++i)
    {
    	x = x / 10;
    }
    #endif

    return x / r[k - 1] % 10;
}

//求某一位上的数字 321, 最低位时k为1
int get_l_digit(int x, int k)
{
    int r[MAX_D] = {1, 10, 100, 1000};

    return x / r[k - 1] % 10;
}

//MSD 递归的方法实现
void msd_radix_sort(int *v, int * aux_v,int left, int right, int k)
{
    int i;
    int j;
    int value;
    int p1;
    int p2;
    int count[NUM_BUCKET];
    int posit[NUM_BUCKET];

    if (left >= right || k > MAX_D)
    {
        return;
    }

    for (i = 0; i < NUM_BUCKET; ++i)
    {
        count[i] = 0;
    }

    for (i = left; i <= right; i++)
    {
        value = get_m_digit(v[i], k);
        count[value]++;                             //统计各桶元素的个数
    }

    posit[0] = 0;                                   //预先计算各桶开始存放位置

    for (i = 1; i < NUM_BUCKET; i++)
    {
        posit[i] = count[i - 1] + posit[i - 1];      //安排各桶元素位置?
    }

    for (i = left; i <= right; i++)
    {
        value = get_m_digit(v[i], k);
        aux_v[posit[value]] = v[i];                 //记录
        posit[value]++;
    }

    j  = 0;
    i  = left;
    while (i <= right)
    {
        v[i++] = aux_v[j++];
    }

    p1 = left;
    for (i = 0; i < NUM_BUCKET; i++)
    {
        p2 = p1 + count[i] - 1;
        msd_radix_sort(v, aux_v, p1, p2, k + 1);
        p1 = p2 + 1;
    }
}


//LSD 递归的方法实现
void lsd_radix_sort1(int *v, int *aux_v, int left, int right, int k)
{
    int i;
    int j;
    int value;
    int count[NUM_BUCKET];
    int posit[NUM_BUCKET];

    if (left >= right || k > MAX_D)
    {
        return;
    }

    for (i = 0; i < NUM_BUCKET; ++i)
    {
        count[i] = 0;
    }

    for (i = left; i <= right; i++)
    {
        value = get_l_digit(v[i], k);
        count[value]++;                             //统计各桶元素的个数
    }

    posit[0] = 0;                                   //预先计算各桶开始存放位置

    for (i = 1; i < NUM_BUCKET; i++)
    {
        posit[i] = count[i - 1] + posit[i - 1];      //安排各桶元素位置
    }

    for (i = left; i <= right; i++)
    {
        value = get_l_digit(v[i], k);
        aux_v[posit[value]] = v[i];                 //记录
        posit[value]++;
    }

    j  = 0;
    i  = left;
    while (i <= right)
    {
        v[i++] = aux_v[j++];
    }

    for (i = 0; i < NUM_BUCKET; i++)
    {
        lsd_radix_sort1(v, aux_v, left, right, k + 1);
    }
}

//LSD 迭代的方法实现
void lsd_radix_sort2(int *v, int *aux_v, int left, int right, int k)
{
    int i;
    int j;
    int value;
    int count[NUM_BUCKET];
    int posit[NUM_BUCKET];

    if (left >= right || k > MAX_D)
    {
        return;
    }

    for (; k <= MAX_D; k++)
    {

        for (i = 0; i < NUM_BUCKET; ++i)
        {
            count[i] = 0;
        }

        for (i = left; i <= right; i++)
        {
            value = get_l_digit(v[i], k);
            count[value]++;                             //统计各桶元素的个数
        }

        posit[0] = 0;                                   //预先计算各桶开始存放位置

        for (i = 1; i < NUM_BUCKET; i++)
        {
            posit[i] = count[i - 1] + posit[i - 1];      //安排各桶元素位置
        }

        for (i = left; i <= right; i++)
        {
            value = get_l_digit(v[i], k);
            aux_v[posit[value]] = v[i];                 //记录
            posit[value]++;
        }

        j  = 0;
        i  = left;
        while (i <= right)
        {
            v[i++] = aux_v[j++];
        }
    }
}

int main(int argc, char const *argv[])
{
    int v[] = {1214, 1199, 65, 197, 6273, 8113, 2218, 0, 9955, 32, 101, 1999, 11, 9990, 87, 60, 81, 10, 5112, 119, 911, 375};
    int a[] = {1214, 1199, 65, 197, 6273, 8113, 2218, 0, 9955, 32, 101, 1999, 11, 9990, 87, 60, 81, 10, 5112, 119, 911, 375};

    int len = sizeof(v) / sizeof(v[0]);
    int *v_t = (int *)malloc(len * sizeof(int));
    if (v_t ==  NULL)
    {
        free(v_t);
        printf("malloc failed\n");
        exit(1);
    }

    print_array(v, len);

    msd_radix_sort(v, v_t, 0, len - 1, 1);
    print_array(v, len);

    memcpy(v, a, sizeof(a));
    lsd_radix_sort1(v, v_t, 0, len - 1, 1);
    print_array(v, len);

    memcpy(v, a, sizeof(a));
    lsd_radix_sort2(v, v_t, 0, len - 1, 1);
    print_array(v, len);

    free(v_t);
    return 0;
}

八大排序

标签:item   gif   int   ++i   const   右值   简单   img   inf   

原文地址:https://www.cnblogs.com/IvanLxy/p/13611334.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!