排序算法

 

1.冒泡排序:

依次比较相邻的两个数,将小数放在前面,大数放在后面。即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。

图解:

#include<stdio.h>
int main(){
    int i,j,n,a[110],t,tt,count;
    scanf("%d",&t);
    while(t--){
        count=0;
    scanf("%d",&n);
    for(i=0;i<n;i++){
        scanf("%d",&a[i]);
    }
    for(i=0;i<n-1;i++){
        for(j=0;j<n-i-1;j++){
            if(a[j]>a[j+1]){
                 count++;
                 tt=a[j];
                 a[j]=a[j+1];
                 a[j+1]=tt;
            }
        }
    }
    printf("%d\n",count);
   }
return 0;
}

2.选择排序:

每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。

 

 

#include<iostream>
#include<cstdio>
using namesapce std;
void SelectionSort(int *num,int n)
{
 int i = 0;
 int min = 0;
 int j = 0;
 int tmp = 0;
 for(i = 0;i < n-1;i++)
 {
 	min = i;//每次讲min置成无序组起始位置元素下标 
    for(j = i;j < n;j++)//遍历无序组,找到最小元素。 
    {
	  if(num[min]>num[j])
	  {
	   min = j;
	  }
	}
	if(min != i)//如果最小元素不是无序组起始位置元素,则与起始元素交换位置 
	{
	  tmp = num[min];
	  num[min] = num[i];
	  num[i] = tmp;
	}
 }
}
 
int main()
{
 int num[6] = {5,4,3,2,9,1};
 int i = 0;
 SelectionSort(num,6);//这里需要将数列元素个数传入。有心者可用sizeof在函数内求得元素个数。 
 for(i = 0;i < 6;i++)
 {
   printf("%d ",num[i]);
 }
 return 0;
}

 3.插入排序:

每步将一个待排序的纪录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。

#include<iostream>
#include<cstdio>
using namespace std;
 int main(void)
 {
     int n, x, i, count = 0;
     int a[10];
     scanf("%d", &n);
     for(i = 0; i < n; i++){
         scanf("%d", &a[i]);
     }
     scanf("%d", &x);

     if(x >= a[n-1]){
        for(i = 0; i < n; i++)
            printf("%d ", a[i]);
         printf("%d\n", x);
     }

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

     if(x > a[0]&& x < a[n-1]){
      for(i = 0; i < n; i++)
      {
         if(a[i] <= x){
             printf("%d ", a[i]);
             count++;
         }
         if(a[i] >= x){
             printf("%d ", x);
             break;
         }
       }

     for(i = count; i < n; i++)
        printf("%d ", a[i]);
     printf("\n");
     }

     return 0;
 }

 4.希尔排序:

是插入排序的一种。是针对直接插入排序算法的改进。不稳定。

 

#include <iostream>
 
using namespace std;
 
int a[] = {70,30,40,10,80,20,90,100,75,60,45};
 
void shell_sort(int a[],int n);
int main()
{
	cout<<"Before Sort: ";
    for(int i=0; i<11; i++)
		 cout<<a[i]<<" ";
	  cout<<endl;
	  shell_sort(a, 11);
   cout<<"After Sort: ";
	  for(int i=0; i<11; i++)
		  cout<<a[i]<<" ";
	  cout<<endl;
	 system("pause");
}
 
void shell_sort(int a[], int n)
{
	int gap;
	for(gap = 3; gap >0; gap--)
	{
		for(int i=0; i<gap; i++)
		{
			for(int j = i+gap; j<n; j=j+gap)
			{
				if(a[j]<a[j-gap])
				{
					int temp = a[j];
					int k = j-gap;
					while(k>=0&&a[k]>temp)
					{
						a[k+gap] = a[k];
						k = k-gap;
					}
					a[k+gap] = temp;
				}
			}
		}
	}
}

 5.归并排序

将两个顺序序列合并成一个顺序序列的方法。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
 
/*该函数将数组下标范围[l1,r1]和[l2,r2]的有序序列合并成一个有序序列*/
void merge(vector<int>& nums, int l1, int r1, int l2, int r2 ) {
	int i = l1;                                               //左半部分起始位置
	int j = l2;                                               //右半部分起始位置
	int n = (r1 - l1 + 1) + (r2 - l2 + 1);                    //要合并的元素个数
	vector<int> temp(n);                                      //辅助数组
	int k = 0;	                                          //辅助数组其起始位置
	while (i <= r1&&j <= r2) {                                //挑选两部分中最小的元素放入辅助数组中
		if (nums[i] < nums[j])
			temp[k++] = nums[i++];
		else
			temp[k++] = nums[j++];
	}
	//如果还有剩余,直接放入到辅助数组中
	while (i <= r1)
		temp[k++] = nums[i++];
	while (j <= r2)
		temp[k++] = nums[j++];
	//更新原始数组元素
	for (int i = 0; i < n;i++)
	{
		nums[l1 + i] = temp[i];
	}
}
 
/*二路归并排序(递归实现)*/
void MergeSort(vector<int>& nums,int start, int end) {
	if (start < end) {
		int mid = (start + end) >> 1;				//分割序列
		MergeSort(nums, start, mid);				//对序列左半部分进行规并排序
		MergeSort(nums, mid + 1, end);				//对序列右半部分进行规并排序
		merge(nums, start, mid, mid + 1, end);                  //合并已经有序的两个序列
	}
}
 
/*二路归并排序(迭代实现)*/
void MergeSort1(vector<int>& nums, int start, int end)
{
	int n = nums.size();
	if (start < end) {
		//step为组内元素个数,step/2为左子区间元素个数
		for (int step = 2; step/2 <n; step *= 2) {
			//每step个元素一组,组内前step/2和后step/2个元素进行合并
			for (int i = 0; i < n; i += step) {
				int mid = i + step / 2 - 1;					//左子区间元素个数为step/2
				if(mid+1<n)							//右子区间存在元素个数则合并
					//左子区间为[i,mid],右子区间为[mid+1, min(i+step-1, n-1)]
					merge(nums, i, mid, mid + 1, min(i + step - 1, n-1));
			}
		}
	}
}
 
int main() {
	vector<int> nums{ 1,4,3,2,5,6,3 };
	MergeSort(nums,0,6);
//	MergeSort1(nums, 0, 6);
	for (auto x : nums)
		cout << x << " ";
	cout << endl;
	return 0;
}

 6.快速排序

首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。

#include <iostream>
using namespace std;

//exchange the 2 items a and b
void swap(int &a, int &b)
{
    if (a == b)
        return;
    a = a + b;
    b = a - b;
    a = a - b;
}

//ergodic the buf and print it
void print(int  *p, int length)
{
    for (int i = 0; i < length; i++)
    {
        cout << p[i] << " ";
    }
}

/*
quitSort
*/ 

int getPartion(int *array, int low, int high)
{
    int key = array[low];
    while (low < high)
    {
        while (low < high && key <= array[high]) //如果array[high]大于键值,那么本就应该在键值右边
            high--;  //因此将high下标向前移动,直至找到比键值小的值,此时交换这两个值
        swap(array[low], array[high]);

        while (low < high && key >= array[low])
            low++;
        swap(array[low], array[high]);
    }
    return low;//返回key值的下标
}



void QuitSort(int *buf,int low,int high)
{
    if (low < high)
    {
        int key = getPartion(buf, low, high);

        QuitSort(buf, low, key - 1);
        QuitSort(buf, key + 1, high);
    }
}

int main(int argc, char *args[])
{
    int buf[10] = { 12, 4, 34, 6, 8, 65, 3, 2, 988, 45 };
    int m = sizeof(buf);
    cout << "排序前:" << endl;
    print(buf, sizeof(buf) / sizeof(int));

    QuitSort(buf, 0, sizeof(buf) / sizeof(int)-1);

    cout << "\n\n\n排序后:" << endl;
    print(buf, sizeof(buf) / sizeof(int));
    getchar();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值