数据结构——排序复习

  1. 插入类排序
    • 直接插入排序:适用于基本有序(减少比较和移动的次数),数量较小的情况
    • 希尔排序:插入排序的基础上引入delta
  2. 交换类排序
    1. 冒泡排序:两两交换,注意change标记位的设计
    2. 快速排序
  3. 选择类排序
    1. 简单选择类排序
    2. 堆排序

希尔排序和插入排序

需要r[0]一个辅助位,相当于temp暂存位

void insSort(int r[],int n)
{
	int i,j;
	for(i = 2;i <= n;i++){
		r[0] = r[i];
		j = i - 1;
		while(r[0] < r[j]){
			r[j+1] = r[j];
			j--;
		}
		r[j+1] = r[0];
	}
}

void ShellInsert(int r[],int n,int delta)
{
    int j;
    for(int i = 1 + delta;i <= n;i++){
    //从第一个子序列的第二个元素开始
        if(r[i] < r[i-delta]){
            r[0] = r[i]; //对r[i]的值进行一个备份
            //将前面的数字全部进行移动
            for(j = i - delta;j > 0&& r[j] > r[0];j -= delta ){
                r[j + delta] = r[j];
            }
            r[j+delta] = r[0];
        }
    }
    for(int i = 1;i <= n;i++)
        cout<>x;
    while(x){
        r[i] = x;
        i++;
        cin>>x;
    }
    int n = i - 1;
    for(i = 0;i < 3;i++){
        cin>>delta[i];
    }
    ShellSort(r,n,delta,3);
    return 0;
}

冒泡排序和快排

  • 快排的本质类似于二叉排序树,在排序好的情况下速度最差

    //冒泡排序算法,相比之前多了一个change的标记元素
    void BubbleSort(int r[],int n)
    {
        int temp;
        bool change = true;
        for(int i = 1;i <= n-1 && change;i++){
            //大循环控制趟数,change减少不必要的循环次数(如已经排序好的数组)
            change = false;
            for(int j = 1;j <= n - i;j++){
                if(r[j] > r[j+1]){
                    temp = r[j];
                    r[j] = r[j+1];
                    r[j + 1] = temp;
                    change = true;
                }
            }
        }
    
    }
    //单趟次的快速排序 (核心也是冒泡排序,类似于希尔和插入排序的关系,这个是分组版本的冒泡排序)
    int QKPass(int r[],int low,int high)
    {
        //选定一个基准,注意单趟次的基准是保持不变的
        int x = r[low];
        while(low < high){
            while(low < high && r[high] >= x)
                high--;
            if(low < high){
                //相当于两者交换位置,此时r[high]变为虚位,右侧均比其大,但左侧没有均比其小
                r[low] = r[high];
                low++;
            }
            while(low < high && x > r[low])
                low++;
            if(low < high){
                r[high] = r[low];
                high--;
            }
        }
        r[low] = x;
        //返回基准所在位置
        return low;
    }
    //完整版本的快速排序
    void QKSort(int r[],int low,int high,int n)
    {
        int pos;
        if(low < high){
            //初次选定一个轴分出左右子表
            pos = QKPass(r,low,high);
            QKSort(r,low,pos - 1,n);
            QKSort(r,pos+1,high,n);
        }
        if(high - low + 1 == n){
        for(int i = 1;i <= high;i++)
            cout<

 简单选择排序和堆排序

一个选出每趟的最小一个选出每趟的最大

//简单选择排序算法 
void selectSort(int r[],int n)
{
	int k;
	for(int i = 1;i <= n-1;i++){
		//控制趟数,每趟选出本趟次最小的数字来 
		k = i;
		for(int j = i + 1;j <= n;j++){
			if(r[j] < r[k])
			    k = j;
		} 
		if(k != i){
			//执行三步交换代码 
		}
	}
}
//除了low以外,low节点(根节点的左右节点均为已经构造好的大根堆)
void Sift(int r[],int low,int high)
{
    bool finished = false;
    int f = low,i = 2*low;
    while(i <= high && !finished){
        if(i < high && r[i] < r[i + 1])
            i++;
        if(r[f] > r[i])
            finished = true;
        else{
            int temp;
            temp = r[f];
            r[f] = r[i];
            r[i] = temp;
            //i记录的是Low的较大节点(该节点最后与根节点交换了),此时开始调换以i为根节点的左右子树为大根堆
            //(此时I位置的树不一定全部大于左右子树)
            f = i;
            i = 2*i;
        }
    }
}


//接受到一个无序数组,并将它调整为一个大根堆函数
void createHeap(int r[],int n)
{
    //由完全二叉的性质,n/2的向下取整是第一个非叶子节点,从该节点开始调整,使其具有大根堆性质
    //然后自底向上逐渐调整,使其可以成为一个大根堆
    for(int i = n/2;i >= 1;i--)
        Sift(r,i,n);
}
void HeapSort(int r[],int n)
{
    int i;
    int temp;
    createHeap(r,n);
    for(i = 1;i <= n;i++)
        cout<= 2;i--){
        //每趟以后换顺序
        temp = r[1];
        r[1] = r[i];
        r[i] = temp;
        Sift(r,1,i - 1);
        for(int j = 1;j <= n;j++)
            cout<

你可能感兴趣的:(数据结构,排序算法,算法)