目录
一:编写双向冒泡排序算法,在正反两个方向交替进行扫描,即第一趟把关键字最大的元素放在序列的最后面,第二趟把关键字最小的元素放在序列的最前面,如此反复进行
二:已知线性表按顺序存储,且每个元素都是不相同的整数型元素,设计把所有奇数移动到所有偶数前面的算法
三:试着重新编写 快速排序的划分算法,使之每次选取的枢轴值都是随机地从当前子表中选择的
四:试着编写一个算法,使之能够在数组L[1...n]中找到第k小的元素(即从小到大排序后处于第k个位置的元素)
五:荷兰国旗问题:设有一个仅由红,白,蓝三种颜色的条块组成的条块序列,请编写算法,使得这些条块按红 白 蓝的顺序排好,即排成荷兰国旗图案
七:编写一个算法,在基于单链表表示的待排序关键字序列上进行简单选择排序
九:设顺序表用数组A[ ]表示,表中元素存储在数组下标1 - m+n范围内,前m个元素递增有序,后n个元素递增有序,设计一个算法,使得整个顺序表有序
十一:设有一个数组中存放了一个无序的关键序列K1,K2,..Kn,现要求将Kn放在将元素排序后的正确位置上,试着编写实现该功能的算法,要求比较关键字的次数不超过n
一:编写双向冒泡排序算法,在正反两个方向交替进行扫描,即第一趟把关键字最大的元素放在序列的最后面,第二趟把关键字最小的元素放在序列的最前面,如此反复进行。
#include<iostream>
using namespace std;
//双向冒泡
void bsort(int a[],int n)
{
int i;
//范围的左右两端
int low=0,high=n-1;
//一趟是否交换过 初始化
bool flag = true;
//循环条件 左端<右端 并且一趟有交换
while(low<high&&flag)
{
//排序前 默认一趟没有交换
flag = false;
//从前向后交换
for(i=low;i<high;i++)
{
if(a[i]>a[i+1])
{
swap(a[i],a[i+1]);
flag = true;
}
}
high--;
//从后向前交换
for(i=high;i>low;i--)
{
if(a[i]<a[i-1])
{
swap(a[i],a[i-1]);
flag = true;
}
}
low++;
}
}
int main()
{
int a[10] = {7,5,9,2,6,4,3,8,1};
bsort(a,9);
for(int i=0;i<9;i++)
{
cout<<a[i]<<" ";
}
return 0;
}
二:已知线性表按顺序存储,且每个元素都是不相同的整数型元素,设计把所有奇数移动到所有偶数前面的算法
#include<iostream>
using namespace std;
void Move(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};
Move(a,9);
for(int i=0;i<9;i++)
{
cout<<a[i]<<" ";
}
return 0;
}
三:试着重新编写 快速排序的划分算法,使之每次选取的枢轴值都是随机地从当前子表中选择的
核心代码
void Partiton2(int a[],int low,int high,)
{
//获取随机下标
int root=low+rand()%(high-low+1);
//交换到第一个
swap(a[low],a[root]);
//i一开始指向low位置
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;
}
四:试着编写一个算法,使之能够在数组L[1...n]中找到第k小的元素(即从小到大排序后处于第k个位置的元素)
#include<iostream>
using namespace std;
int min_k(int a[],int low,int high,int k)
{
//快速排序划分算法
//i一开始指向low位置
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];
//若最后基准的位置为k的话 那么基准就是第k小
else if(i>k) return min_k(a,low,i-1,k);
//若最后基准的位置>k的话 那么基准左边递归去找
else return min_k(a,i+1,high,k);
//若最后基准的位置<k的话 那么基准右边递归去找
}
int main()
{
int a[10] = {0,7,5,9,2,6,4,3,8,1};
cout<<min_k(a,1,9,8)<<endl;
return 0;
}
五:荷兰国旗问题:设有一个仅由红,白,蓝三种颜色的条块组成的条块序列,请编写算法,使得这些条块按红 白 蓝的顺序排好,即排成荷兰国旗图案
#include<iostream>
using namespace std;
//按照负数0 正数来排数组
void num(int a[],int n)
{
//三个指针的指向 初始化
int i=0,j=0,k=n-1;
//循环体 j<=k
while(j<=k)
{
int v;
if(a[j]>0) v=1;
else if(a[j]==0) v=0;
else v=-1;
//switch判断a[j]的值
switch(v)
{
//负数 和i交换
case -1:
swap(a[i],a[j]);
i++;
j++;
break;
//0 遍历指针+1
case 0:
j++;
break;
//正数 和k交换
case 1:
swap(a[j],a[k]);
k--;
break;
}
}
}
int main()
{
int a[9] = {0,-1,-2,0,0,3,-4,1};
num(a,8);
for(int i=0;i<8;i++)
{
cout<<a[i]<<" ";
}
return 0;
}
六:已知由n(n>=2)个正整数构成的集合A={ak|0<=k<n},将其划分成为两个不相交的子集A1和A2。元素个数分别是n1和n2,A1和A2中的元素之和分别为S1和S2,设计一个算法,满足|n1-n2|最小且|S1-S2|最大
#include<iostream>
using namespace std;
//快排
void seta(int a[],int n,int low,int high)
{
//非递归
int flag=1;
//取中间值 后面与基准值进行比较
int k=(high-low)/2;
//非递归条件
while(flag)
{
//快排
//i一开始指向low位置
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]);
//返回基准元素的位置
//如果基准值刚好等于s1的右端 结束
if(i==k-1) flag=0;
//如果基准值小于 则在右端进行快排 继续找到中间值的位置
else if(i<k-1) low=i+1;
//否则在左端
else high = i-1;
}
//计算两个集合的和
int s1=0,s2=0;
for(int i=0;i<k;i++)
{
s1+=a[i];
cout<<"s1="<<a[i]<<" ";
}
cout<<endl;
for(i=k;i<n;i++)
{
s2+=a[i];
cout<<"s2="<<a[i]<<" ";
}
cout<<endl;
cout<<abs(s1-s2)<<endl;
}
int main()
{
int a[9]={0,-1,-2,0,-10,3,-4,1};
seta(a,8,0,8);
return 0;
}
七:编写一个算法,在基于单链表表示的待排序关键字序列上进行简单选择排序
#include<iostream>
using namespace std;
//链表存储结构
typedef struct lnode{
int data;
struct lnode *next;
}lnode,*linklist;
int a[10]={7,5,9,2,6,4,3,8,1};
int n=9;
void buildlist(lnode *L)
{
lnode *s,*r=L;
r->data=a[0];
if(n==1) r->next=NULL;
else{
for(int i=1;i<n;i++)
{
s=(lnode *)malloc(sizeof(lnode));
s->data=a[i];
r->next=s;
r=r->next;
}
r->next=NULL;
}
}
void disp(lnode *L)
{
lnode *s=L;
while(s)
{
cout<<(s->data)<<" ";
s=s->next;
}
cout<<endl;
}
//简单选择排序
void selectsort(linklist &l)
{
//五个指针 遍历表的指针的初始化
lnode *h = l;
lnode *p,*s,*r,*q;
//将表置空
l= NULL;
//最外面的循环条件
while(h!=NULL)
{
//最大节点和工作指针的初始化
s=p=h;
//前驱节点的初始化
q=r=NULL;
//每一趟开始遍历
while(p!=NULL)
{
//碰到更大的节点
if(p->data>s->data)
{
//更新最大节点的位置
s=p;
//更新最大节点的前驱
r=q;
}
q=p;
p = p->next;
//工作指针向后遍历时前驱指针和工作指针向后移
}
//若最大的是表头 将遍历表的指针后移
if(s==h) h = h->next;
else
{
r->next = s->next;
}
//插入结果链表当中
s->next = l;
//更新结果链表的头
l=s;
}
}
int main()
{
lnode L;
lnode *l = &L;
buildlist(l);
selectsort(l);
disp(l);
return 0;
}
八:试着设计一个算法,判断一个数据序列是否构成一个小根堆
#include<iostream>
using namespace std;
//判断是不是小根堆
int is_min(int a[],int len)
{
//最后的序号为偶数
if(len%2==0)
{
//判断单只节点
if(a[len/2]>a[len]) return 0;
//判断双支节点
for(int i=len/2;i>=1;i--)
{
if(a[i]>a[2*i]||a[i]>a[2*i-1])
return 0;
}
}
else
{
//为奇数
for(int i=len/2;i>=1;i--)
{
//判断双支节点
if(a[i]>a[i*2]||a[i]>a[i*2+1])
return 0;
}
}
return 1;
}
int main()
{
int a[8]={1,1,3,2,5,4,0};
cout<<is_min(a,6)<<endl;
return 0;
}
九:设顺序表用数组A[ ]表示,表中元素存储在数组下标1 - m+n范围内,前m个元素递增有序,后n个元素递增有序,设计一个算法,使得整个顺序表有序
#include<iostream>
using namespace std;
void insertsort(int a[],int m,int n)
{
//两个遍历指针
int i,j;
//第一个遍历范围
for(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[8]={0,1,3,5,7,2,4,9};
insertsort(a,4,3);
for(int i=1;i<=7;i++) cout<<a[i]<<" ";
return 0;
}
十:有一种简单的排序算法,称为计数排序,这种排序算法对一个待排序的表(用数组表示)进行排序,并将排序结果存放到另一个新的表中,必须注意的是,表中所有待排序的关键码互不相同,计数排序算法针对表中的每个记录,扫描待排序的表一趟,统计表中有多少个记录的关键码比该记录的关键码小,假设针对某个记录统计出的计数值为c,则这个记录在新有序表中的合适存放位置为c
#include<iostream>
using namespace std;
void countsort(int a[],int b[],int n)
{
//遍历每一趟
int count=0;
for(int i=0;i<n;i++)
{
//找到每个元素小的个数
count = 0;
for(int j=0;j<n;j++)
{
if(a[j]<a[i]) count++;
}
b[count] = a[i];
}
}
int main()
{
int a[6]={3,5,7,2,4,9},b[6];
countsort(a,b,6);
for(int i=0;i<6;i++) cout<<b[i]<<" ";
return 0;
}
十一:设有一个数组中存放了一个无序的关键序列K1,K2,..Kn,现要求将Kn放在将元素排序后的正确位置上,试着编写实现该功能的算法,要求比较关键字的次数不超过n
#include<iostream>
using namespace std;
int quicksort(int a[],int low,int high)
{
//i一开始指向high位置
int i=high;
//从倒数第二个开始遍历到头
int p=a[high];
for(int j=high-1;j>=0;j--)
{
//如果大于基准值
if(a[j]>p) swap(a[--i],a[j]);
//交换到后面去
}
//将基准元素插入到最终的位置
swap(a[high],a[i]);
//返回基准元素的位置
return i;
}
int main()
{
int a[5]={3,5,7,2,4};
cout<<quicksort(a,0,4)<<endl;
return 0;
}