几种常见的排序算法的代码实现

以下是我用代码实现几种排序算法的过程,其中注释标注一些我觉得值得注意的地方做个分享

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<sys/timeb.h> //获得系统时间

#define MAX 10

//获得系统时间
long getSystemTime()
{
struct timeb tb;
ftime(&tb);
return tb.time*1000+tb.millitm;
}

void output(int a[],int length)
{
int i;
for(i=0;i<length;i++)
{
printf("%d",a[i]);
}
}

void Bubble(int a[],int length)
{
//升序
int i,j;
for(i = 0;i<length;i++)
{
for(j=length-1;j>i;j–)
{
if(a[j-1]>a[j])
{
int temp = a[j-1];
a[j-1] = a[j];
a[j] = temp;
}
}
}

}

//选择排序
void select_sort(int a[],int length)
{
//选择排序减少了交换次数,效率O(n*n)
//思路认为当前值为最小值,从剩下的元素中寻找比当前值更小的元素,交换其位置
//外循环从位置0开始
int i,j;
for(i=0;i<length;i++)
{
int min = i;
for(j = i+1;j<length;j++)
{
if(a[min]>a[j])
{
min = j;
}
}
if(min!=i)
{
int temp = a[min];
a[min] = a[i];
a[i] = temp;
}

}

}

//插入排序
void Insert_sort(int arr[],int length)
{
int i,j;

//首先默认第0个元素是已经排序好的遍历之后未排序的数组元素,所以从第一个元素开始遍历
for(i=1;i<length;i++)
{
    if(arr[i]<arr[i-1])
    {
    //用一个temp保存当前的arr[i]值
    int temp = arr[i];


    //从已经排序好的数组的末尾开始遍历
    for(j=i-1;j>=0&&temp<arr[j];j--)
    {
        //往后移一个元素
        arr[j+1] = arr[j];
    }
       //找出比当前元素小的元素,在这之后插入这个值
       arr[j+1] = temp;

    }

}

}

//希尔排序:
//先进行分组,再分别进行插入排序
//分组间隔依据是长度/3+1
void shell_sort(int a[],int length)
{
int i,j,k;

//分组的间隔
int gap = length;

do
{
   gap = gap/3+1;
  //先找出每组的第一个元素
  for(i=0;i<gap;i++)
  {

    //i+gap是每一组的第一个元素,下标为1,相当于a1
    for(j=i+gap;j<length;j+=gap)
    {
        if(a[j]<a[j-gap])
        {
            int temp = a[j];
            for(k=j-gap;k>=0&&a[k]>temp;k-=gap)
            {
                a[k+gap] = a[k];
            }
               a[k+gap] = temp;

        }

    }

}
    }

while(gap>1);
}

//快速排序
//从小到大排序,从右往左找到一个比基准值小的值,,从左往后找比基准值大的值
void Quick_Sort(int a[],int start,int end)
{
//一个指向开始,一个指向末尾
int i = start;
int j = end;
int temp = a[start];

//进入循环的条件
if(i<j)
{
    //循环
    while(i<j)
    {
        //从右往左找
        for(j=end;j>i;j--)
        {
            if(a[j]<temp)
            {
                a[i] = a[j];
                i++;
                break;
            }
        }
        //从左往右找
        for(;i<j;i++)
        {

            if(a[i]>temp)
            {
                a[j] = a[i];
                j--;
                break;
            }

        }
    }
    //循环结束当前位置放基准值
    a[i] = temp;

    //递归
    Quick_Sort(a,start,i-1);
    Quick_Sort(a,i+1,end);

}
}

void merge(int a[],int start,int end,int mid,int *temp)
{
//合并,同时对两个分组进行循环,将小的存放在前面
int i_start = start;
int i_end = mid;

int j_start = mid+1;
int j_end = end;

//表示辅助空间中的元素个数
int count = 0;

while(i_start<=i_end&&j_start<=j_end)
{
    if(a[i_start]<a[j_start])
    {
        temp[count] = a[i_start];
        i_start++;
        count++;
    }
    else
    {
        temp[count] = a[j_start];
        count++;
        j_start++;
    }
}


 //遍历将剩余的元素都赋值到辅助空间中,因为i_start<i_end所以当条件成立则还有数值
 while(i_start<=i_end)
 {
     temp[count] = a[i_start];
     i_start++;
     count++;
  }

   while(j_start<=j_end)
 {
     temp[count] = a[j_start];
     count++;
     j_start++;
  }

//辅助空间的数据覆盖到原数组
int i;
for(i=0;i<end-start+1;i++)
{
  a[start+i] = temp[i];
}

}

//交换函数
void Swap(int arr[],int a,int b)
{
int temp =arr[a];
arr[a] = arr[b];
arr[b] = temp;

}

//index:待调整的节点的下标//

void HeapAdjust(int a[],int index,int length)
{
//首先记录当前节点的位置
int max = index;

  //左孩子的下标
  int leftchild = 2*index+1;

  //右孩子的下标
  int rightchild = 2*index+2;

  //调整当前的堆,如果其左右孩子的下标已经超出当前堆的长度,则循环结束
  if(leftchild<length&&a[leftchild]>a[max])
  {
      //记录最大的下标
      max = leftchild;

  }

  if(rightchild<length&&a[rightchild]>a[max])
   {
       max = rightchild;
   }

   if(max!=index)
   {
       //交换值
       Swap(a,index,max);

    //递归调用,调整交换完但是不满足的堆,当该max对应的位置的左右孩子超出length时,就不会再递归了
      HeapAdjust(a,max,length);
   }

}

//堆排序(最大堆)
//堆排序是一种选择排序,步骤是:首先是初始化堆,将最大的元素放到堆顶,接着将堆顶元素和最后一个元素进行交换
//最后一个元素不参与排序,剩下的元素再次组成一个最大堆

void HeapSort(int a[],int length)
{
//首先初始化堆,找到最后一个非叶子节点
int i;
for(i=length/2-1;i>=0;i–)
{

 //调整堆,只需要调整叶子节点
  HeapAdjust(a,i,length);


 }
//交换第一个节点和最后一个节点的位置
 int j;
 for(j=length-1;j>=0;j--)
 {
     Swap(a,0,j);
     //继续调整,从上往下调整
     HeapAdjust(a,0,j);
 }

}

//归并排序,将已经排序好的小的部分合并成一个整体
void Merge_Sort(int a[],int start,int end,int *temp) //temp是用来暂时存放排序好的小的组
{
//退出条件
if(start>=end)
{
return;
}

//递归分组
int mid = (start+end)/2;
//左半边
Merge_Sort(a,start,mid,temp);

//右半边
Merge_Sort(a,mid+1,end,temp);

//合并
merge(a,start,end,mid,temp);

}

int main()
{
int i;
int arr[MAX];
int arr1[MAX] = {3,5,4,2,1,0,6,8,9,7};
srand((unsigned int)time(NULL)); //随机数种子,播种子
for(i=0;i<MAX;i++)
{
arr[i] = rand()%MAX;

}
output(arr1,MAX);


// 申请一个数组空间
int *temp = (int *)malloc(sizeof(int)*MAX);
long start = getSystemTime();
printf("\n");
printf("开始时间:%ld\n",start);
//int length = sizeof(arr)/sizeof(int);

//int arr1[MAX] = {1,2,0,3,6,7,5,4,9,8};
// output(arr,MAX);
// 冒泡排序
//Bubble(arr,MAX);

//选择排序
//select_sort(arr,MAX);

//插入排序
//Insert_sort(arr,MAX);

//希尔排序

// shell_sort(arr,MAX);

//快速排序
//Quick_Sort(arr,0,length-1);

//归并排序
//Merge_Sort(arr1,0,MAX-1,temp);

//堆排序
HeapSort(arr1,MAX);

printf("\n");
output(arr1,MAX);

printf("\n");

long end = getSystemTime();
printf("结束时间%ld\n",end);
long time = end-start;
printf("\n");
printf("耗时%ld毫秒\n",time);
free(temp);
return 0;

}
最后附上一张算法的时间空间复杂度和稳定性的比较

猜你喜欢

转载自blog.csdn.net/qq_39304481/article/details/90905784