插入排序
直接插入排序
void InsertSort(int a[],int n){
int i,j;
for(i=2;i<=n;i++){
if(a[i]<a[i-1]){
a[0]=a[i];
for(j=i-1;a[0]<a[j];--j){
a[j+1]=a[j];
}
a[j+1]=a[0];
}
}
折半插入排序
void InsertSort(int a[],int n){
int i,j,mid,low,high;
for(i=2;i<=n;i++){
a[0]=a[i];
low=1;
high=i-1;
while(low<high){
if(a[0]<a[mid])
high=mid-1;
else
low=mid+1;
}
for(j=i-1;j>high-1;--j){
a[j+1]=a[j];
}
a[high+1]=a[0];
}
希尔排序
void ShellSort(int a[],int n){
for(int dk=n/2;dk>0;dk=dk/2){
for(i=dk+1;i<n;i++){
a[0]=a[i];
for(j=i-dk;j>0&&a[0]<a[j];j-=dk){
a[j+dk]=a[j];
}
a[j+dk]=a[0];
}
}
}
//当步长为数组时
void shellSort(int a[],int n,int d[],int t){
int i,j,k,;
for(i=0;i<t;i++){
for(j=d[i];j<n;j++){
a[0]=a[j];
for(k=j-d[i];k>=0&&a[0]<a[k];k=k-d[i]){
a[k+d[i]]=a[k];
}
a[k+d[i]]=a[0];
}
}
}
选择排序
简单选择排序
void selectSort(int a[],int n){
int i,k,min;
for(i=0;i<n;i++){
min=i;
for(j=i+1;j<n;j++){
if(a[j]<a[min]) min=j;
}
if(i!=min) swap(a[i],a[min]);
}
}
堆排序
//建立大根堆
void BuildMaxHeap(int a[],int k,int len){
for(int i=n/2;i>0;i--){
HeapAdjust(a[],i,len);
}
}
//调整子树
void HeapAdjust(int a[],int k,int n){
int a[0]=a[k];
for(int i=2*k;i<len;i*=2){
if(i<len&&a[i]<a[i+1]){
i++;
}
if(a[i]<a[k]) 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/2;i>1;i--){
swap(a[i],a[1]);
HeapAdjust(a,1,i-1);//注意这里不是0而是1
}
}
交换排序
冒泡排序
void changeSort(int a[],int n){
for(int i=0;i<n-1;i++){
flag=false;
for(j=n-1;j>i;j--){
if(a[j]<a[j-1]){
swap(a[j],a[j-i]);
flag=true;
}
}
if(falg=false)
return;
}
}
快速排序
//划分
void Partition(int a[],int low,int high){
int pivot=a[low];
while(low>high){
while(low<high &&a[high]<pivot) --high;
a[low]=a[high];
while(low<high &&a[low]>pivot) ++low;
a[high]=a[low];
}
a[low]=pivot;
return low;
}
//排序
void QuickSort(int a[],int low,int high){
if(low<high){
int pivotPos=Partition(a,low,high);
QuickSort(a,1,pivotPos-1);
QuickSort(a,pivotPos+1,high);
}
}
应用题
1.非递归方法实现快速排序。
2.快速排序,随机选择枢轴
思路:首先选定基准轴和第一个元素对调,遍历之后的元素,凡是大于基准的元素都按原本次序排列形成数组a[],结束第一次遍历后,调换初始的基准和an的当前末尾元素。
void Partition(int a[],int low,int high){
int rand=low +rand()%(high-low+1);
swap(a[low],a[rand]);
int pivot=a[low];
int i=low;
for(int j=low+1;j<=high;j++){
if(a[j]<pivot){
swap(a[++i],a[j]);
}
swap(a[i],a[low]);
}
return i;
}
3.顺序存储,把所有奇数移动到偶数前
思路:从前往后依次查找第i个奇数,从后往前依次查找第i个偶数,比大小交换次序
void move(int a[],int len){
int i=0;j=len-1;
while(i<j){
while(i<j&&a[i]%2!=0) i++;
while(i<j&&a[j]%2!=1) j--;
if(i<j){
swap(a[i],a[j]);
}
i++;
j--;
}
}
4.双向冒泡,正反交替扫描,第一趟把最大关键词放最后,第二趟把最小关键词放最前
void bubble(int a[],int len){
int low=0,high=len-1;
bool flag=true;
while(low<high&&flag)
flag=false;
for(int i=0;i<high;i++){
if(a[i+1]<a[i]){
swap(a[i],a[j=i+1]);
flag=true;
}
high--;
for(int i=high;j>low;j--){
if(a[i]<a[i-1]){
swap(a[i],a[i-1]);
flag=true;
}
i++:
}
}
5.荷兰国旗问题。
typedef enum{RED,WHITE,BLUE} color;
void Flag_Arrange(color a[],int n){
int i=0;j=0;k=n-1;
while(j<=k){
switch(a[j]){
case RED:
Swap(a[i],a[j]);i++;j++;
break;
case WHITE:
j++;
break;
case BLUE:
Swap(a[i],a[k]);k--;
}
}
}
集合n划分为2个不相交的子集A1,A2,元素个数分别是n1,n2,元素和分别是s1,s2。
设计算法满足|n1-n2|最小且|s1-s2|最大。
void setPartiotion(int a[],int n){
int low=0,high=n-1,high0=n-1,low0=0;
int k=n/2;
int flag=1;
int pivot=a[low];
while(flag){
while(low<high){
while(low<high && pivot>a[low]) --i;
a[high]=a[low];
while(low<high && pivot<a[high]) --high;
a[low]=a[high];
}
a[low]=pivot;
if(low==k-1) flag=0;
else if(low<k-1){
low0=++low;
high=high0;
}
else{
high0=--high;
low=low0;
}
}
在数组L[1…n]中找出第k小的元素
//快速排序法
void search(int a[],int low,int high,int k){
int pivot=a[low];
int low_temp=low;
int high_temp=high;
while(low<high){
//基本
}
a[low]=pivot;
if(low==k){
return a[low];
}
else if(low>k){
return search(a,low_temp,low-1,k);
}
else{
return search(a,low+1,high_temp,k);
}
}
//堆排序法
void buildMax(int a[],int len){
for(int i=0;i<len/2;i++){
heapAdjust(a,i,len);
}
}
void heapAdjust(int a[],int k,int len){
a[0]=a[k];
for(int i=2*k;i<len;i*=2){
if(a[i]>a[i+1]){
i++;
}
if(a[i]<a[k]) break;
else{
a[i]=a[k];
i=k;
}
a[k]=a[0];
}
}
void heapSort(int a[],int len,int k){
buidMax(a,len);
for(int i=len,int j=1;len>1,j<k;i--,k++){//修改调整的躺输
swap(a[i],a[1]);
heapSort(a,1,i-1);
}
cout<<a[k];
}
判断是否是小根堆
void isMinHeap(int a[],int len){
if(len%2==0){
if(a[len/2]>a[len]) return false;//判断单分支结点
for(int i=len/2-1;i>1;i--){
if(a[i]>a[i*2]||a[i]>a[i*2+1]){
return false;
}
}
else{
for(int i=len/2;i>1;i--){
if(a[i]>a[i*2]||a[i]>a[i*2+1]){
return false;
}
}
}
}
}
链表排序
简单选择排序
//这是自己vs调试出来的,总算链表的感觉回来了一点
ListNode* selectSort(ListNode *L) {
ListNode *p, *q, *r,*s,*t,*la;//r为最小值结点,s为最外层比较遍历,p为当前结点,q为p前驱
r=s= L->next;
//L->next = NULL;
t = NULL;
la = L;
int min = r->val;
while (s) {
q = s;
p = q->next;
while (p) {
if (p->val < r->val) {
r = p;
t = q;
}
else {
p = p->next;
q = q->next;
}
}
t->next = r->next;//断开
r->next = la->next;
la->next = r;
la = r;
r = s;
//s = s->next;
if (s->next == NULL) {
return L;
}
}
};
//正解:每趟在原始链表中摘下最大关键字结点,插入到链表最前
void selectSort(LinkList L){//不带头结点
LinkNode *p,*q,*r,*s,*h=L;
L=NULL;
while(h!=NULL){
p=s=h;q=r=NULL;//p为q为p的前驱,s记忆最大结点,r为s前驱,
while(p!=NULL){
if(p->data>s->data){
s=p;
r=q;
}
q=p;p=p->link;
}
if(h==s){
h=h->Link;
}
else{
r->link=s->link;
}
}
}
直接插入排序