IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> DS -> 排序 -> C++实现 -> 正文阅读

[数据结构与算法]DS -> 排序 -> C++实现

theory into practice. 实现各类排序方法

插入排序: 直接插入排序、折半插入排序、希尔排序
交换排序:冒泡排序、快速排序
选择排序:简单选择排序、堆排序
归并排序
基数排序

  • 直接插入排序
  • 折半插入排序
  • 希尔排序
  • 冒泡排序
  • 快速排序
  • 简单选择排序
  • 堆排序
  • 归并排序
  • 基数排序

归并排序

JZ51 数组中的逆序对
解题思路:一开始使用的是两重for循环嵌套,结果5/6测试用例通过。后看到题目要求时间复杂度为 o ( n log ? n ) o(n\log n) o(nlogn),需要对进行改进。
首先备份一下两重for循环的代码:

class Solution {
public:
    int InversePairs(vector<int> data) {
        int p = 0;
        for(vector<int>::iterator it1 = data.begin(); it1 != data.end(); it1++)
        {
            for(vector<int>::iterator it2 = it1 + 1; it2 != data.end(); it2++)
            {
                if(*it2 < *it1) p++;
            }
        }
        return p % 1000000007;
    }
};

接下来是改进方法:采用归并排序,分而治之。
思路:

  1. 递归划分到最小操作区间
  2. 合并,将两个操作区间合并为一个区间【用临时数组存储】,然后将临时数组赋值给最初的数组
class Solution {
public:
    long cnt;
    int InversePairs(vector<int> data)
    {
        cnt = 0;
        if(data.size() == 0) return 0;
        mergesort(data,0,data.size() - 1);
        return cnt % 1000000007;
    }
    void mergesort(vector<int>& A, int low, int high)
    {
        if(low < high)
        {
            int mid = (low + high) / 2;
            mergesort(A,low,mid);
            mergesort(A,mid+1,high);
            vector<int> tmp;
            merge(A,tmp,low,mid,high);
        }
    }
    void merge(vector<int>& A,vector<int> B,int low,int mid,int high)
    {
        int i, j;
        for(i = low, j = mid + 1; i <= mid && j <= high;)
        {
            if(A[i] > A[j]) 
            {
                B.push_back(A[j++]);
                cnt += mid - i + 1; 
            }
            else if(A[i] <= A[j]) B.push_back(A[i++]);
        }
        while(i <= mid) B.push_back(A[i++]);
        while(j <= high) B.push_back(A[j++]);
        
        int k = 0;
        for(int i = low; i <= high && k < B.size(); i++)
        {
            A[i] = B[k++];
        }
    }
    
};

难点

  1. vector<int>tmp的位置,按照算法笔记的介绍来说,用来存储暂时的合并结果的数组应该在merge()函数之外
    解决方法: 加在mergesort()函数体内,递归划分到最小操作区间之后,开始merge之前
  2. 计数器cnt的使用
    解决方法: 归并排序的“精髓”就是两个有序的区间合并为一个有序的区间,即:两个数组A,B,若A[i] < B[j],则A[0], A[1] ... A[i-1]均小于B[j]。所以可用来求逆序对,若A[i]>B[j],则有一个逆序对,cnt+1
  3. “临时”向量的使用,tmp作为一个储存临时结果的容器,整个归并排序的过程需要的是这个容器,而不是容器里的内容,因此在参数传递中,不需要使用引用,即void merge(vector<int>& A,vector<int> B,int low,int mid,int high),A需要加引用,因为是源数据,而B不需要加引用

堆排序(优先队列)

首先,放上堆排序的代码

//A[0]空着
//建立大根堆
void BuildMaxHeap(int A[],int len)
{
	for(int i = len / 2; i > 0; i--)
		HeadAdjust(A,i,len);
}

void HeadAdjust(int A[],int k, int len)
{
	A[0] = A[k];
	for(int i = 2 * k; i <= len; i *= 2) // 2 * k 是k位置元素的左孩子, i + 1 是k位置元素的右孩子
	{
		if(i < len && A[i]<A[i+1]) i++; //左右孩子中选出最大的
		if(A[0] >= A[i]) break;
		else
		{
			A[k] = A[i];
			k = i;
		}
	}
	A[k] = A[0];
}

//堆排序
void HeapSort(int A[], int len)
{
	BuildMaxHeap(A,len);
	for(int i = len; i > 1; i--)
	{
		swap(A[i],A[1]);//A[i]为堆顶
		HeadAdjust(A,1,i-1);
	}
} 

然后,是本质是堆排序的优先队列
语法见STL总结,注意:top可返回堆顶,而pop只能删除,无法得到删除的数据
具体应用:JZ40 最小的K个数

class Solution {
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) 
    {
        /* 优先队列解决*/
        vector<int> ans;
        if(k == 0 || k > input.size()) return ans;
        priority_queue<int,vector<int>> pri_que;
        for(const int val : input) //赋值语句 类似于for(;;)
        {
            if(pri_que.size() < k) pri_que.push(val);
            else
            {
                if(val < pri_que.top())//当前堆非最小的k个数
                {
                    pri_que.pop();
                    pri_que.push(val);
                }
            }
        }
        while(!pri_que.empty())
        {
            ans.push_back(pri_que.top());
            pri_que.pop();
        }
        return ans;
    }
};

C++中sort()函数

语法见STL总结
具体应用:JZ40 最小的K个数

class Solution {
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) 
    {
        /*sort()函数解决*/
        vector<int> ans;
        if(k == 0 || k > input.size()) return ans;
        sort(input.begin(),input.end());
        for(int i = 0; i < k; i++)
            ans.push_back(input[i]);
        return ans;
        
    }
};

快速排序

首先,放上算法

void QuickSort(ElemType A[], int low, int high)
{
	if(low < high)
	{
		int pivotpos = Partition(A, low, high);
		QuickSort(A, low, pivotpos - 1);
		QuickSort(A, pivotpos + 1, high);
	}
}
/*一次划分后,能够确定pivot的位置*/
int Partition(ElemType A[], int low, int high)
{
	ElemType pivot = A[low];
	while(low < high)
	{
		while(low < high && A[high] >= pivot) --high;//从后往前找到第一个比pivot小的值的位置
		A[low] = A[high];
		while(low < high && A[low] <= pivot) ++low;// 从前往后,找到第一个比pivot大的值的位置
		A[high] = A[low];
	}
	A[low] = pivot;
	return low;
}

具体应用:JZ40 最小的K个数

class Solution {
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) 
    {
        /*快排解决*/
        vector<int> ans;
        if(k == 0 || k > input.size()) return ans;
        QuickSort(input, 0, input.size()-1);
        for(int i = 0; i < k; i++)
            ans.push_back(input[i]);
        return ans;   
    }
    void QuickSort(vector<int>& data,int low, int high)
    {
        if(low < high)
        {
            int pivotpos = Partition(data,low,high);
            QuickSort(data, low, pivotpos - 1);
            QuickSort(data, pivotpos + 1, high);
        }
    }
    int Partition(vector<int>&data,int low, int high)
    {
        int pivot = data[low];
        while(low < high)
        {
            while(low < high && data[high] >= pivot) high--;
            data[low] = data[high];
            while(low < high && data[low] <= pivot) low++;
            data[high] = data[low];
        }
        data[low] = pivot;
        return low;
    }
};
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-03-04 15:50:05  更:2022-03-04 15:51:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 16:27:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码