笔面试常考数据结构算法总结

e最近开始投各种技术类的岗位,于是乎觉得必须补一下之前的数据结构算法知识了,因为真的很重要!几乎每家面试都会问到其中的几个算法。本文部分算法是从其他大神博主那边搬运的,大家可以搜索相关算法查看其他大神的解说和思路~~~~
稳定性:排序算法是否稳定,根据序列中相同的元素排序前后的位置来判断,如果两个相同元素经过排序后,其相对位置未发生变化,则称该排序是稳定的。
注:对数组型序列的插入操作要考虑移位;后移:a[i+1]=a[i];前移:a[i-1]=a[i].
1.插入类排序
1)直接插入排序
定义,对于一个待排序列,如a[ ]=1,3,4,6,5,7,8;令i=1,首先取出a[1],将a[1]插入到序列中,当前a[1]只需和a[0]相比,然后将其插入适当位置,i++;每次将a[i]插入到a[0]至a[i-1]的序列中(因为a[i]之前的序列已经有序)。
对于n个数,要进行n-1趟插入排序,所以其时间复杂度为O(n^2),其空间复杂度为O(1),该排序是稳定的;
若待排序列为正序,时间复杂度为O(n),当要排序的数据量很大时,不适合用该方法。 直接插入排序常出现在笔试的选择题中。
C++代码实现:

int Insort(int A[],length){
        int temp=0;
        for(int i=1;i<length;i++)
          {
              if(A[i]<A[i-1])
              {
                 temp=A[i];
                 for(int j=i-1;j>=0&&A[j]>temp;j--)
                 {
                    A[j+1]=A[j];
                 }
                 A[j+1]=temp; //将temp放在该放的位置
             }
          }    
       return A;         
}                          

2)折半插入排序
其定义为,首先通过折半查找(转查找算法)找到数据要插入的位置,再对序列中的数据进行移动并插入待排数据;时间复杂度为O(n^2);稳定排序;
折半的概念来自于折半查找
插入类排序的空间复杂度均为O(1).
3)希尔排序
定义,是一种缩小增量的排序;将待排序列分割为几组,每次分割要基于一定的增量,每次的增量不一样;在小组内排好序后,再进行下一次分组;
第一次分组,d=10/2=5
第二次分组,d=3


最后一趟的增量d=1;
平均时间复杂度为O(1.3),最坏时间复杂度为O(n^2);不稳定排序
空间复杂度:O(1)
希尔排序的C++实现:

int Shellsort(int A[],int length){
        int gap=0;
        int temp=0;
      for(gap=length/2;gap>0;gap/=2)
      {
            for(int i=gap;i<length;i++)
            {
             for (int j=i;j>=gap;j-=gap)
             {
               if(A[j]<A[j-gap])
               {
                 temp=A[j];
                 A[j]=A[j-gap];
                 A[j-gap]=temp;
               }
               else
               {
                 break;
               }  
             }
           }
         }
        return A;
}

说明:第二层j的值从i开始,每次跳到j-gap,且j的值大于等于gap,是因为当i往后移的时候,gap之前的数已经逐渐排好序了,后面j只需要控制在比较gap之后的元素即可。

2.交换排序:
1)冒泡排序
定义:从头开始比较序列中的元素,每次保留较大(小)的数,直到一次循环结束,选出最大(小)数;
每一趟排序会将当前序列的最大(小)值放在其相应的位置上。从算法就可以知道,执行两层循环所需要的时间即为其时间复杂度;
最坏以及平均时间复杂度为O(n^2)
空间复杂度:O(1). 稳定排序
C++实现:
每一趟排序,当j和i相遇的时候,说明前i个值已经排好了,即已经将前i次每次找出的最小值放在相应位置上,所以j的值只需大于i即可:

int BubbleSort(int []A){
   int temp;
   for(int i=0;i<A.length();i++)
      {
         for(int j=A.length()-1; j>i; j--)
             {
                if(A[j]<A[j-1])
                {
                   temp=A[j];
                   A[j]=A[j-1];
                   A[j-1]=temp;
                  } 
              }
      }
    return A;
}    

2)快速排序
定义,从序列中选出一个数作为“枢轴”,通常会选择第一个数,也可以选择中间的数;在序列的首尾各有一个指针low、high,首先从high指向的数开始,与枢轴元素做比较,若遇到比枢轴小的元素,则将其挖出来放到low指向的位置;下一步则从当前low开始往后移动,若遇到比枢轴大的元素,将其挖出来放到当前high指向的位置;这样经过一次移动完毕即low==high时,枢轴的左边的数都比它小,其右边的数都比它大。再对其左、右的子序列递归调用快排。
C++实现:

int QuickSort(int A[],int l,int r){
      int low=l;
      high=r;
      int pivot=A[low];       
      if(l<r)
         {
           while(low<high && pivot<=A[high])
           {
               high--;
               }
           if(low<high) A[low++]=A[high];          
           while(low<high && pivot>=A[low])
           {
             low++;
             }
           if(low<high){ 
            A[high--]=A[low];
           }     
         A[low]=pivot;
         QuickSort(A,int l,int low-1);
         QuickSort(A,int low+1,int r);         
    }
   return A;
 }                            

时间复杂度推导公式可以查看相关资料,主要考虑其每次一分为二的特性。
快速排序的最好以及平均时间复杂度均为O(nlogn)
最坏时间复杂度为O(n2),对于快排,越有序的序列时间复杂度越高;
空间复杂度为O(logn)至O(n). 不稳定排序

3.选择排序
1)简单选择排序
2)堆排序
堆排序;首先创建一个大顶或小顶堆;每次则可以找到最大或最小元素;将最大或最小元素与最后一个元素交换,接着继续调整堆;
最坏时间复杂度O(nlogn),最好时间复杂度O(nlogn),平均时间复杂度O(nlogn);空间复杂度为O(1);

//调整堆中的元素时,假设没有交换的子节点保持着最大(最小)堆性质,所以只对经过交换的子节点进行调整
void swap(int &a, int &b)
{
    int tmp = 0;
    tmp = a;
    a = b;
    b = tmp;

}
void ShiftHeap(int A[],int maxSign,int n)//maxSign为当前根节点,n表示n个节点;
{
    int j = 2 * maxSign + 1;
    int temp=A[maxSign];
    while (j < n)
    {
        if (j+1 < n && A[j] < A[j + 1])
        {
            j = j + 1;
        }
        if (temp > A[j])  break;
        else
        {
            A[maxSign] = A[j];
            maxSign = j;
            j = 2 * maxSign + 1;
        }
    }
    A[maxSign] = temp;
}

//正式开始堆排序,首先创建一个大顶或小顶堆,接着将顶端元素与最后一个元素交换,继续进行交换后的调整;
void Heapsort(int A[],int n)
{
    for (int j = n / 2 - 1; j >= 0; j--)
    {
        ShiftHeap(A, j, n);
    }
    //交换过程:
    for (int i = n - 1; i >= 1; i--)
    {
        swap(A[i], A[0]);   
        ShiftHeap(A, 0, i);
    }
}

不得不说,每次只对度为2以上的节点进行调整,大大减少了时间复杂度,使其达到logn级别,真的hin棒了!
4.归并排序
5.二叉树排序

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值