经典排序算法C++

冒泡排序:

依次比较相邻的两个元素,如果前者大于后者,则交换顺序。第一趟完成后最后的元素是最大的,然后针对所有的元素重复以上的步骤,除了最后一个。时间复杂度n^2

void bubblesort(vector<int>& arr)
{
	for (int i = 0; i < arr.size()-1; i++)
	{
		for (int j = 0; j < arr.size()-1-i; j++)
		{ 
			if (arr[j]> arr[j+1])
			{
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
}

选择排序:

在序列中,找到最小元素,放到序列的起始位置作为已排序序列;然后,再从剩余未排序元素中继续寻找最小元素,放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

void selectionsort(vector<int>& arr)
{
   
    for (int i = 0;i < arr.size()-2;i++)
    {
        int min = arr[i],index=i;
        for (int j = i+1;j < arr.size()-1;j++)
        {
            if (min>arr[j])
            {
                min = arr[j];
                index = j;
            }
        }
        arr[j] = arr[i];
        arr[i] = min;
    }
}

插入排序:

1.从第一个元素开始,该元素可以认为已经被排序
2.取出下一个元素,在已经排序的元素序列中从后向前扫描
3.如果该元素(已排序)大于新元素,将该元素移到下一位置
4.重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
5.将新元素插入到该位置中
6.重复步骤2

void insertionsort (vector<int>& arr)
{
   
    for (int i = 1;i < arr.size()-1;i++)
    {
        int temp = arr[i];
        for (int j = i-1;j >= 0&& temp < arr[j];j--)
        {
                arr[j+1] = arr[j];
        }
        arr[j+1] = temp;
    }
}
    

快速排序:

选定第一个数作为基准,将设置左右两个指针,目标是将比基准数大的数放在右边,小的数放在左边,如果有不满足的条件的,则两个指针交换,直到两个指针重合,将此时所指的数和基准数交换。

void quicksort(vector<int>& arr, int left, int right)  
{  
    if(left>right) 
       return; 
           
    int i = left, j = right, temp = arr[left];  
    while (i < j)  //如果i==j,此时则为正中心的位置,需要把基准数换过去
    {  
        while(i < j && arr[j]>= temp) // 从右向左找第一个小于x的数  
           j--;   
        while(i < j && arr[i]<= temp) // 从左向右找第一个大于等于x的数  
            i++;   
        if(i < j)  
        {
           int t = arr[i];
           arr[i] = arr[j];
           arr[j] =t;
        }
    }  
    arr[left] = arr[i];
    arr[i] =temp;
    quicksort(arr, left, i - 1); // 递归调用  
    quicksort(arr, i + 1, right);   
} 

堆排序:

堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。

大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]  

小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]  

堆排序的基本思路:

  a.将无序序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆;

  b.将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端;

  c.重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。

class Solution {
public:
     */
    void heapAdjust(vector<int>& arr, int start, int end) {
        int temp = arr[start];
        
        for(int i=2*start+1; i<=end; i*=2) {
            //左右孩子的节点分别为2*i+1,2*i+2
            
            //选择出左右孩子较小的下标
            if(i < end && arr[i] < arr[i+1]) {
                i ++; 
            }
            if(temp >= arr[i]) {
                break; //已经为大顶堆,=保持稳定性。
            }
            arr[start] = arr[i]; //将子节点上移
            start = i; //下一轮筛选
        }
        
        arr[start] = temp; //插入正确的位置
    }
    
    
    void heapSort(vector<int>& arr) {
        if(arr == null || arr.length == 0)
            return ;
        
        //建立大顶堆
        for(int i=arr.length/2; i>=0; i--) {
            heapAdjust(arr, i, arr.length-1);
        }
        
        for(int i=arr.length-1; i>=0; i--) {
            swap(arr, 0, i);
            heapAdjust(arr, 0, i-1);
        }
        
    }
    
    void swap(vector<int>& arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

}
    

排序算法的稳定性:如果Ai = Aj,排序前Ai在Aj之前,排序后Ai还在Aj之前,则称这种排序算法是稳定的。通俗地讲就是保证排序前后两个相等的数的相对顺序不变。

猜你喜欢

转载自blog.csdn.net/snow_jie/article/details/81033518