12-数据结构-排序

发布时间:2024年01月01日

排序算法
一.比较类排序
1.交换排序
(1).冒泡

#include <stdio.h>

void PrintContext(char sort[], int size)
{
	for(int i=0;i<size;i++)
	{
		printf("%d ", sort[i]);
	}
	printf("\n");
}

//冒泡排序
//Reverse 0:正向排序
//Reverse 1:反向排序
void OrderBubbleSort(char sort[], int size, int Reverse)
{
	for(int i=0; i<size; i++)
	{
		for(int j=0; j<size -i-1; j++)
		{
			if(0 == Reverse)
			{
				if(sort[j] > sort[j+1])
				{
					char tmp;
					tmp = sort[j+1];
					sort[j+1] = sort[j];
					sort[j] = tmp;
				}
			}
			else
			{
				if(sort[j] < sort[j+1])
				{
					char tmp;
					tmp = sort[j+1];
					sort[j+1] = sort[j];
					sort[j] = tmp;
				}
			}
		}
	}
}

int main()
{
	char sort1[8] = {1,3,4,2,5,6,8,7};
	char sort2[10] = {1,3,4,2,10,9,5,6,8,7};
	printf("sort1:");
	PrintContext(sort1, sizeof(sort1));
	printf("sort1 Order:");
	OrderBubbleSort(sort1, sizeof(sort1),0);
	PrintContext(sort1, sizeof(sort1));
	printf("sort1 ReverseOrder:");
	OrderBubbleSort(sort1, sizeof(sort1),1);
	PrintContext(sort1, sizeof(sort1));
	
	printf("sort2:");
	PrintContext(sort2, sizeof(sort2));
	printf("sort2 Order:");
	OrderBubbleSort(sort2, sizeof(sort2),0);
	PrintContext(sort2, sizeof(sort2));
	printf("sort2 ReverseOrder:");
	OrderBubbleSort(sort2, sizeof(sort2),1);
	PrintContext(sort2, sizeof(sort2));
	return 0;
}

运行结果

sort1:1 3 4 2 5 6 8 7 
sort1 Order:1 2 3 4 5 6 7 8 
sort1 ReverseOrder:8 7 6 5 4 3 2 1 
sort2:1 3 4 2 10 9 5 6 8 7 
sort2 Order:1 2 3 4 5 6 7 8 9 10 
sort2 ReverseOrder:10 9 8 7 6 5 4 3 2 1 


(2).快速

#include <stdio.h>

void PrintContext(char sort[], int size)
{
	for(int i=0;i<size;i++)
	{
		printf("%d ", sort[i]);
	}
	printf("\n");
}

void ExChangeNum(char sort[], char num1, char num2)
{
	char tmp;
	tmp = sort[num1];
	sort[num1] = sort[num2];
	sort[num2] = tmp;
}

//快速排序
void QuickSort(char sort[], int start, int end)
{
	if(start > end)
		return ;
	int start_loop = start;
	int end_loop = end;
	char Base = sort[start];
	while(start_loop < end_loop)
	{
		while(start_loop < end_loop && sort[end_loop] >= Base)
		{
			end_loop=end_loop-1;
		}
		while(start_loop < end_loop && sort[start_loop] <= Base)
		{
			start_loop = start_loop+1;
		}

		if(start_loop < end_loop)
			ExChangeNum(sort,start_loop, end_loop);
	}

	ExChangeNum(sort,start, start_loop);
	QuickSort(sort, start, end_loop-1);
	QuickSort(sort, end_loop+1, end);
	
}

int main()
{
	char sort1[8] = {1,3,4,2,5,6,8,7};
	char sort2[10] = {3,1,4,2,10,9,5,6,8,7};
	printf("sort1:");
	PrintContext(sort1, sizeof(sort1));
	printf("sort1 Order:");
	QuickSort(sort1, 0, sizeof(sort1)-1);
	PrintContext(sort1, sizeof(sort1));
	
	printf("sort2:");
	PrintContext(sort2, sizeof(sort2));
	printf("sort2 Order:");
	QuickSort(sort2, 0, sizeof(sort2)-1);
	PrintContext(sort2, sizeof(sort2));
	return 0;
}

运行结果

sort1:1 3 4 2 5 6 8 7 
sort1 Order:1 2 3 4 5 6 7 8 
sort2:3 1 4 2 10 9 5 6 8 7 
sort2 Order:1 2 3 4 5 6 7 8 9 10


2.插入排序
(1).简单插入

比较简单,不详细描述
(2).希尔

希尔排序本质上也是直接插入排序,但是会先进行预排序,使原序列更接近有序序列,最后将预排之后的序列进行直接插入排序。
序列:arr1[] = {9,8,7,6,5,4,3,2,1,0},如果用直接插入排序,那么需要往后移动元素的次数为n*(n-1)/2,也就是45次;
序列呢:arr2[] = {0,1,2,3,5,4,8,7,6,9};,用直接插入排序,需要移动元素的次数仅为4次。
希尔排序就是根据步长设置,先分区域排序,减少元素移动次数

一个数组为{9,7,8,4,6,1,3,2},有数组我们可知这个数组中的元素个数为8个
(1)第一次步长:step = n(数组元素个数) / 2(这里/号为c语言中的取整符号) => 8/2=4;
先9与6,7和1,8和3,4和2比
{6,1,3,2,9,7,8,4}
(2)第二次步长:step = step(这里的step为第一次的step的值)/2 => 4/2 = 2;
再6,3,9,8比,1,2,7,4比
{3,1,6,2,8,4,9,7}
(3)第三次步长:step = step(这个同上)/2 => 2/2 = 1;
最后所有比
{1,2,3,4,6,7,8,9}

#include <stdio.h>
 
void arr_out(int a[8])
{
    int i = 0;
    for(i = 0;i < 8;i++)
    {
        printf("%d ",a[i]);
    }
    printf("\n");
}
 
void arr_sort(int *p,int n)
{
    int step = 0;//步长
    int temp = 0;//用来保存第二段数据
    int i,j;
 
    for(step = n / 2;step > 0;step /= 2)
    {
        for(i = step;i < n;i++)
        {
            temp = p[i];
            for(j = i - step;j >= 0 && p[j] > temp;j -= step)
            {
                p[j + step] = p[j];
                //当满足条件时第一次j+step = i;后面的j+step = 上一次j的值
            }
            p[j + step] = temp;
        }
    }
}
 
int main()
{
    int a[8] = {9,7,8,4,6,1,3,2};
 
    arr_sort(a,8);//排序函数
    arr_out(a);//输出函数
 
    return 0;
}


3.选择排序


(1).简单选择

比较简单,不详细描述


(2).堆:以下4步,完成堆排序

1).数组转化为二叉树
父节点下标为k(k>0),那么其左孩子下标为2*k,右孩子下标为2*k+1
leftchild=parent×2+1;
rightchild=parent×2+2;
parent=(child-1)/2。
2).最大堆排序 (Heapify)
从左右孩子中选择最大的孩子结点,与父结点交换,并递归调整交换后的孩子结点
3).创建最大堆(CreateHeap)
单对一个节点进行最大堆调整并不能使整个二叉树形成最大堆,所以我们需对末尾节点的父节点依次向前进行最大堆排序,从而使得二叉树形成最大堆。
4)、堆排序
根节点为最大值,将其与末尾子节点交换
对根节点进行最大堆调整,以交换的末尾节点不参与调整 ,使根节点为下一个最大值
不断变换,缩小最大堆调整范围,只剩根节点,完成节点排序

#include <stdio.h>
#define size 10
 
void Swap(int *num, int i, int j)
{
	int temp;
	temp = num[i];
	num[i] = num[j];
	num[j] = temp;
}   
 
// 最大堆调整
void Heapify(int *num, int len, int k)
{
	if (k < len)
	{
	  int root = k;           // 根结点
	  int lchild = 2*k + 1;   // 左孩子结点
	  int rchild = 2*k + 2;   // 右孩子结点
	  // 查找左右孩子结点中的最大结点
	  if (lchild < len && num[root] < num[lchild])
	  {
		  root = lchild;
	  }   
	  if (rchild < len && num[root] < num[rchild])
	  {
		  root = rchild;
	  }   

	  // 交换最大结点到根结点
	  if (root != k)
	  {
		  Swap(num, root, k);
		  // 每次交换都可能影响到对应孩子结点子树的顺序
		  // 所以需要对交换后的孩子结点子树进行最大堆调整
		  Heapify(num, len, root);
	  }   
	}   
}
  
  // 创建最大堆
void CreateHeap(int *num, int len)
{
	int i;
	// 最后一个结点下标
	int last = len - 1;
	// 最后一个结点的父结点下标
	int parent = (last - 1) / 2;
	// 从最后一个结点的父结点到根结点,依次进行最大堆调整
	for (i = parent; i >= 0; i--)
	{
	  Heapify(num, len, i);
	}   
}   
  
  // 堆排序
void HeapSort(int *num, int len)
{
	// 创建最大堆并进行最大堆调整
	CreateHeap(num, len);
	printf("最大堆调整!\n");
	int i;
	// 依次取出根结点(最大值)
	for (i = len - 1; i >= 0; i--)
	{
	// 将最大堆的根结点(最大值)换到最后一个结点
	Swap(num, i, 0);
	// 交换后二叉树的根结点发生了改变,故还需对根结点做最大堆调整(已交换的末尾结点不参与调整)
	// 而此时根结点小于所有父结点,因而在调整时只需考虑最大孩子的分支即可
	Heapify(num, i, 0);
	}   
}   

int main()
{
    int i, num[size] = {8, 4, 3, 1, 6, 9, 5, 7, 2, 0};
    HeapSort(num, size);
    
    for (i = 0; i < size; i++)
    {
        printf("%d ", num[i]);
    }   
    printf("\n");
    return 0;
}   


4.归并排序
(1).二路归并

二路归并的步骤是先拆分,再合并,具体步骤如下
{ 5,9,8,6,1,3,2,4 }
=>{5,9,8,6} {1,3,2,4}
=>{5,9} {8,6} {1,3} {2,4}
=>{5} {9} {8} {6} {1} {3} {2} {4}
=>{5,9} {6,8} {1,3} {2,4}
=>{5,6,8,9} {1,2,3,4}
=>{1,2,3,4,5,6,8,9}

(2).多路归并

和二路归并类似,不做具体描述


二.非比较排序
1.计数排序


2.桶排序


3.基数排序

文章来源:https://blog.csdn.net/sishen4199/article/details/132839266
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。