王道数据结构查找排序

简单选择排序

//数组-简单选择排序
#include<bits/stdc++.h>
using namespace std;
void sort(int a[],int n){
	int k;
	for(int i=0;i<n;i++){
		k=i;
		for(int j=i+1;j<n;j++){
			if(a[j]<a[k]) k=j;
		}
		swap(a[k],a[i]);
	}
}
int main(){
	int a[5]={3,6,1,9,4};
	sort(a,5);
	for(int i=0;i<5;i++){
		cout<<a[i]<<" ";
	}
	cout<<endl;
	return 0;
} 

顺序查找 找到后与前一个元素交换

// 线性表中检索概率不等时,可用如下策略提高检索的效率
//若找到指定结点则将该结点与前驱结点进行交换
//使得经常被检索的结点尽量位于表的前面
//设计在顺序结构的线性表上实现该策略的顺序检索算法

//算法思想:从头开始遍历,若找到,与前置结点进行交换
//若没找到,返回-1 
#include<bits/stdc++.h>
using namespace std;
int search(int a[],int n,int k){//k是要查找的值
     int i; 
	 for(i=0;i<n;i++){
     	if(a[i]==k) break;
	 } 
	 if(i>0&&i<n){
	 	int t=a[i-1];
	 	a[i-1]=a[i];
	 	a[i]=t;
	 	return i-1;
	 }
	 else return -1;
	
} 
int main(){
	int a[6]={1,2,3,4,5,6};
	cout<<search(a,5,3)<<endl;//返回的是2的位置,即1 
	return 0;
} 

双向冒泡

//双向冒泡排序(第一趟把最大的放在最后面,第二趟把最小的放在最前面)
//算法思想:if已经有序就不用交换了
//否则,奇数趟:从左向右遍历,if左>右,交换,每一趟会将最大值放在后面 
//偶数趟:从右向左遍历,if右<左,交换 ,每一趟会将最小值放在前面
#include<bits/stdc++.h>
using namespace std;
void bsort(int a[],int n){
	int low=0,high=n-1;//范围 
	bool flag=true;//判断一趟是否交换过,如果没有交换说明已经有序
	while(low<high&&flag){
		flag=false;
		for(int i=low;i<high;i++){
		if(a[i]>a[i+1]){
			swap(a[i],a[i+1]);
			flag=true;
		}
		
	 } 
	high--;
	for(int i=high;i>low;i--){
		if(a[i]<a[i-1]){
			swap(a[i],a[i-1]);
			flag=true;
		}
	}
	low++;
	}
		
}
int main(){
	int a[7]={3,5,2,6,1,8,7};
	bsort(a,7);
	for(int i=0;i<7;i++){
		cout<<a[i]<<" ";
	}
	cout<<endl;
	return 0;
} 

快速排序

//快速排序的另一种算法
//传统的是i从左往右找比p大的值放在右边,j从右往左找比p小的值放在左边
//这里是随机产生p,j从左往右依次找比p小的换到左边 
//rand()%100:0~100的随机数 
#include<bits/stdc++.h>
using namespace std;
int partition2(int a[],int low,int high){
	//获取随机下标
    //交换到第一个
     //i开始指向low位置
    //从第二个开始遍历到结束
    //if小于基准值 交换到前面去
    //将基准元素插入到最终位置
    //返回基准元素的位置	
	int root=low+rand()%(high-low+1);
    swap(a[low],a[root]);
    int i=low;
    int p=a[low];
	for(int j=low+1;j<=high;j++){	
		if(a[j]<p){
			swap(a[++i],a[j]);
		}
	}
	swap(a[low],a[i]);
	return i;
	 
}
int main(){
	int a[6]={5,1,4,6,7,3};
	cout<<partition2(a,0,5);
	return 0;
}

快速排序–第k小的数

//第k小的元素  基于快速排序时间复杂度O(n)
//算法思想:因为一趟快速排序后可以确定基准元素的位置,所以先进行一趟快速排序 
//如果基准元素的位置=k 则找到了第k小的元素
//如果基准元素的位置>k 在基准元素左边找
//如果基准元素的位置<k 在基准元素右边找
#include<bits/stdc++.h>
using namespace std;
int min_k(int a[],int low,int high,int k){
	int i=low;
	int p=a[low];//基准元素指向第一个元素 
	for(int j=low+1;j<=high;j++){//从第二个开始遍历到结束 
		if(a[j]<p){//如果小于基准元素 
			swap(a[++i],a[j]);//交换到前面去 
		}
	}
	swap(a[low],a[i]);//将基准元素插入到最终位置 
	
	if(i==k) return a[i];
	else if(i>k) return min_k(a,low,i-1,k);
	else return min_k(a,i+1,high,k); 
}
int main(){
	int a[10]={0,4,3,5,2,1,6,8,7};
	cout<<min_k(a,1,8,8);
	return 0;
} 

快速排序–|n1-n2|最小且|s1-s2|最大

//将一个集合划分为两个子集合,子集合的个数分别是n1,n2,子集合的元素之和分别是s1,s2
//设计一个尽可能高效的算法使得|n1-n2|最小且|s1-s2|最大
//算法思想:|n1-n2|最小即个数均分 |s1-s2|最大可以用快速排序
//一趟快速排序后会确定一个基准元素的位置,基准元素左边都小于基准元素,右边都大于基准元素
//if基准元素的位置正好均分这个集合 分好了
//if基准元素的位置在中间位置右边,左边还需要再分
//if基准元素的位置在中间位置左边,右边还需要再分
#include<bits/stdc++.h>
using namespace std;
void part(int a[],int n,int low,int high){
	int flag=1;
	int m=(high-low)/2;
	while(flag){
		int i=low;
	int p=a[low];//第一个为基准元素
	for(int j=low+1;j<=high;j++){//从第二个开始遍历到结束 
		if(a[j]<p){//如果小于基准元素 交换 
			swap(a[++i],a[j]); 
		}
	} 
	//将基准元素插入到最终位置,此时i就是最后基准元素的位置 
	swap(a[low],a[i]);

	if(i==m-1) flag=0;//结束 
	else if(i<m-1) low=i+1;
	else high=i-1;
	}
	
	
	int s1=0,s2=0;
	for(int i=0;i<m;i++){
		s1+=a[i];
		cout<<a[i]<<" ";
	}
	cout<<endl;
	for(int i=m;i<n;i++){
		s2+=a[i];
		cout<<a[i]<<" ";
	}
	cout<<endl;
	cout<<abs(s1-s2)<<endl; 
}
int main(){
	int a[10]={0,-1,-2,0,-10,3,-4,1};
	part(a,8,0,8);
	return 0;
} 

二分查找(折半查找)

//折半查找/二分查找/起始low为1,high为ST.length 
//算法思想:根据起始位置和终止位置将查找序列一分为二
//找mid值,若mid=要查找的x,找到了
//若mid>x,在mid-1左边找
//若mid<x,在mid+1右边找
#include<bits/stdc++.h>
using namespace std;
typedef struct{
	int a[10]={0,1,2,3,4,5,6,7,8};//从1~8开始找 
	int length=8;
}ST;
int bin(ST s,int x,int low,int high){
	while(low<=high){
		int mid=(low+high)/2;
		if(s.a[mid]>x){
	      return bin(s,x,low,mid-1);		
		}else if(s.a[mid]<x){
			return bin(s,x,mid+1,high);
		}else{
			return mid;
		}
	}
} 
int main(){
	ST s;
	cout<<bin(s,3,1,8)<<endl;
	return 0;
} 
//再写一个二分查找/数组
#include<bits/stdc++.h>
using namespace std;
int a[10]={0,1,4,6,7,8,9};//只看后面六个数 
int bin(int l,int r,int x){
	while(l<=r){
		int mid=(l+r)/2;
		if(a[mid]<x) l=mid+1;
		else if(a[mid]>x) r=mid-1;
		else return mid;
	}
	return -1;
}
int main(){
	int ans=bin(1,6,8);
	cout<<ans<<endl;
	return 0;
}

直接插入排序

//直接插入排序 顺序表前m个元素递增,后n个元素递增,设计一个算法使得整个顺序表递增
//算法思想:将数组a[1...m+n]视为一个已经经过m趟插入排序的表,
//则从m+1趟开始,将后n个元素依次插入到前面的有序表中
#include<bits/stdc++.h>
using namespace std;
void insertsort(int a[],int m,int n){
	//两个遍历指针i,j
	//两层遍历范围
	//复制哨兵
	//后移
	//插入哨兵值
	int i,j;
	for(int i=m+1;i<m+n;i++){
		a[0]=a[i];
		for(j=i-1;a[j]>a[0];j--){
			a[j+1]=a[j];
			
		}
		a[j+1]=a[0];
	} 
}
int main(){
	int a[10]={0,1,3,5,7,2,4,9};
	insertsort(a,4,3);
	for(int i=1;i<=7;i++) cout<<a[i]<<" ";
	return 0;
} 

计数排序

//计数排序 (该方法关键码的比较次数为n^2) 
//算法思想:对每个元素,统计关键字比它小的元素个数,然后把它放入另一个数组对应的位置上 
#include<bits/stdc++.h>
using namespace std;
void countsort(int a[],int b[],int n){
	for(int i=0;i<n;i++){
		int count=0;
		for(int j=0;j<n;j++){
			if(a[j]<a[i]) count++;
		}
		b[count]=a[i];
	}
}
int main(){
	int a[6]={4,6,3,2,7,9};
	int b[6];
	countsort(a,b,6);
	for(int i=0;i<6;i++){
		cout<<b[i]<<" ";
	}
	cout<<endl;
	return 0;
} 
 

在这里插入图片描述

按照奇数偶数排序,所有奇数移到偶数前面

//把奇数移动到偶数前面
//算法思想:i从左到右找偶数,j从右到左找奇数,找到后交换
//直到 j在i的左面 说明查找完毕
#include<bits/stdc++.h>
using namespace std;
void sort(int a[],int n){
	int i=0,j=n-1;
	while(i<j){
		while(i<j&&a[i]%2==1) i++;//找到了偶数位置 
		while(i<j&&a[j]%2==0) j--;//找到了奇数位置
		if(i<j){//如果偶数位置在奇数前面 
			swap(a[i],a[j]);
			i++;//改范围 
			j--; 
		} 
		
	}
}
int main(){
	int a[10]={7,5,9,2,6,4,3,8,1};
	sort(a,9);
	for(int i=0;i<9;i++){
		cout<<a[i]<<" ";
	} 
	cout<<endl;
	return 0;
}

荷兰国旗问题 按照红白蓝排序 --按负数 0 正数排序

//荷兰国旗问题:设有一个仅有红白蓝三种颜色的条块组成的条块序列,
//请编写一个时间复杂度为O(n)的算法,使得这些条块按红白蓝的顺序排好,即排成荷兰国旗图案
//算法思想:将该问题转化为按照负数、0、整数来排数组
//设置三个指针i,j,k,i=0,j=0,k=n-1,j为工作指针
//if a[j]<0 与a[i]交换,i,j都向后移 
//if a[j]=0 i不动,j向后移
//if a[j]>0 与a[k]交换,j不动,k向前移
#include<bits/stdc++.h>
using namespace std;
void num(int a[],int n){
     //三个指针的指向 初始化
	 //循环条件
	 int i=0,j=0,k=n-1;
	 while(j<k){
	 	int v;
	 	if(a[j]>0) v=1;
	 	else if(a[j]<0) v=-1;
	 	else v=0;
	 	switch(v){
	 		case -1:swap(a[i],a[j]);i++;j++;break;
	 		case 0:j++;break;
	 		case 1:swap(a[j],a[k]);k--;break;
		 }
	 }	
}

int main(){
	int a[10]={0,-1,-2,1,-1,4,6,0};
	num(a,8);
	for(int i=0;i<8;i++)
	   cout<<a[i]<<" ";
	return 0;
}

不用switch

//荷兰国旗问题:设有一个仅有红白蓝三种颜色的条块组成的条块序列,
//请编写一个时间复杂度为O(n)的算法,使得这些条块按红白蓝的顺序排好,即排成荷兰国旗图案
//算法思想:将该问题转化为按照负数、0、整数来排数组
//设置三个指针i,j,k,i=0,j=0,k=n-1,j为工作指针
//if a[j]<0 与a[i]交换,i,j都向后移 
//if a[j]=0 i不动,j向后移
//if a[j]>0 与a[k]交换,j不动,k向前移
#include<bits/stdc++.h>
using namespace std;
void num(int a[],int n){
     //三个指针的指向 初始化
	 //循环条件
	 int i=0,j=0,k=n-1;
	 while(j<k){
	 	if(a[j]<0){
	 		swap(a[i],a[j]);
	 		i++;j++;
		 } else if(a[j]==0){
		 	j++;
		 }else{
		 	swap(a[j],a[k]);
		 	k--;
		 }
	 }	
}

int main(){
	int a[10]={0,-1,-2,1,-1,4,6,0};
	num(a,8);
	for(int i=0;i<8;i++)
	   cout<<a[i]<<" ";
	return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值