数据结构算法总结(十个算法,全是干货)

目录

1、二分查找:(折半查找)

2、直接选择排序 (不稳定)

3、冒泡排序:

4、(直接)插入排序:(稳定)

5、折半插入排序:

6、希尔插入排序:(不稳定)

7、快速排序:(不稳定)

8、堆排序:

9、归并排序:

10、基数排序:

小结​编辑


1、二分查找:(折半查找)

二分查找的前提是线性表中的记录必须是关键码有序(通常从小到大有序),线性表必须采用顺序存储。

二分查找仅适用于有序数据二分查找仅适用于数组。小数据量下,线性查找性能更佳。当数据量 较小时,线性查找反而比二分查找更快。

int Binary_Search(SeqList L,Elem Type key){
    int low = 0,high = L.length - 1,mid;
    while(low <= high){
        mid = (low + high)/2; //取中间位置
        if(L.elem[mid] == key){
            return mid;  //查找成功返回所在位置
        }else if{L.elem[mid] > key){
            high = mid -1;  //从前半部分继续查找
        }else{
            low = mid + 1;  //从后半部分继续查找
        }
    }
    return -1;  //查找失败,返回-1
}

时间复杂度为O(\log n):在二分循环中,区间每轮缩小一半,因此循环次数为\log_{2}n

空间复杂度为O(1):指针 i 和 j 使用常数大小空间。

2、直接选择排序 (不稳定)

时间复杂度为O(n^{2})

空间复杂度为O(1)

void select_Sort(int A[],int N)    /*选择排序*/
{
    int i,j,k,temp;
    for(i=1;i<N;i++){
        k = i;
        for(j=i+1;j<=N;j++){
            if(A[k]>A[j]) k=j;
        }  //每次循环找出一个最小元素,A[k]
        if(k!=i){
            temp = A[k];
            A[k] = A[i];
            A[i] = temp;
        }  //交换A[k]和A[i]
    }
}

3、冒泡排序:

两两比较相邻记录的关键码,如果反序则交换,直到没有反序的记录为止。

/*冒泡排序*/
void bubbleSort(int nums[],int size){
    //外循环:未排序区间为[0,i]
    for(int i = size - 1;i > 0;i--){
        //内循环:将未排序区间[0,i]中的最大元素交换至该区间的最右端
        for(int j = 0;j < i;j++){
            if(nums[j] > nums[j+1]){
                int temp = nums[j];
                nums[j] = nums[j+1];
                nums[j+1] = temp;
            }
        }
    }
}

/*冒泡排序(优化标志)*/
void bubbleSortWithFlag(int nums[],int size){
    //外循环:未排序区间为[0,i]
    for(int i = size - 1;i > 0;i--){
        bool flag = false;
        //内循环:将未排序区间[0,i]中的最大元素交换至该区间的最右端
        for(int j = 0;j < i;j++){
            if(nums[j] > nums[j+1]){
                int temp = nums[j];
                nums[j] = nums[j+1];
                nums[j+1] = temp;
                flag = true;
            }
        }
        if(!flag)
            break;
    }
}

4、(直接)插入排序:(稳定)

/*插入排序*/
void insertionSort(int nums[],int size){
    //外循环:已排序元素数量为1,2,...,n
    for(int i = 1;i < size; i++){
        int base = nums[i],j = i - 1;
        //内循环:将base插入到已排序部分的正确位置
        while(j >= 0 && nums[j] > base){
            //将nums[j]向右移动一位
            nums[j+1] = nums[j];
            j--;
        }
        //将base赋值到正确位置
        nums[j + 1] = base;
    }
}
            

5、折半插入排序:

void BinInsertSort(RecType R[],int n)
{
    int i, j, low, high, mid;
    RecType tmp;
    for (i=1;i<n;i++){
        if(R[i].key<R[i-1].key)  //反序时
            tmp = R[i];        //将R[i]保存到tmp中
            low = 0;
            high = i-1;
            while(low<=high){        //在R[low..high]中查找插入的位置
                mid=(low+high)/2;    //取中间位置
                if(tmp.key<R[mid].key
                    high = mid - 1;   //插入点在左半区
                else
                    low = mid + 1;    //插入点在右半区
            }                         //找位置high+1
            for(j=i-1;j>=high+1;j--)  //记录后移
                R[j+1] = R[j];
            R[high+1] = tmp;  //插入tmp
        }
    }
}
    

6、希尔插入排序:(不稳定)

void shell_Sort(int A[],int N,int d[],int t)
{
    int i,j,k,h;
    for(k=0;k<t;k++)  /*进行t遍插入排序*/
    {
        h=d[k];  /*当前增量*/
        for(i=h+1;i<=N;i++)
        {
            j=i-h;
            A[0]=A[i];  /*步长为h*/
            while(j>0&&A[0]<A[j])  /*找插入位置并后移*/
            {
                A[j+h]=A[j];  /*后移*/
                j=j-h;  /*继续向前(左)查找*/
            }
            A[j+h]=A[0];
        }
    }
}

7、快速排序:(不稳定)

int quickPass(int A[],int low,int high)
{
    int i=low;j=high;
    A[0]=A[i];
    while(i<j){  /*来回比较法的一次划分*/
        while(i<j&&A[j]>=A[0])  /*从右向左*/
            j--;
        if(i<j)
            A[i++]=A[j];
        while(i<j&&A[i]<A[0])  /*从左向右*/
            i++;
        if(i<j)
            A[j--]=A[i];
    }
    A[i]=A[0];  /*i就是A[0]最终的位置*/
    return i;
}
/* 快速排序类 */
// 快速排序类-哨兵划分
int partition(int nums[],int left,int right){
    // 以 nums[left] 为基准数
    int i = left,j = right;
    while(i<j){
        while(i<j && nums[j] >= nums[left]){
            // 从右向左找首个小于基准数的元素
            j--;
        }
        while(i<j && nums[i] <= nums[left]){
            // 从左向右找首个大于基准数的元素
            i++;
        }
        // 交换这两个元素
        swap(nums, i, j);
    }
    // 将基准数交换至两子数组的分界线
    swap(nums, i, left);
    // 返回基准数的索引
    return i;
}
// 快速排序类-快速排序
void quickSort(int nums[],int left,int right){
    // 子数组长度为 1 时终止递归
    if(left >= right){
        return;
    }
    // 哨兵划分
    int pivot = partition(nums,left,right);
    // 递归左子数组、右子数组
    quickSort(nums,left,pivot - 1);
    quickSort(nums,pivot + 1;right);
}

8、堆排序:

void sift(RecType R[],int low,int high)  //调整堆的算法
{  
    int i = low,j = 2*i;  // R[j] 是 R[i] 的左孩子
    RecType tmp = R[i];
    while(j <= high)
    {
        if(j < high && R[j].key<R[j+1].key) 
            j++;   // j 指向大孩子
        if(tmp.key < R[j].key)  // 双亲小
        {
            R[i]=R[j];  // 将R[j]调整到双亲结点位置
            i = j;  // 修改i和J值,以便继续向下筛选
            j = 2*i;
        }
        else break;  // 双亲大:不再调整
    }
    R[i] = tmp;
}

堆排序算法

void HeapSort(RecType R[],int n)
{
    int i;
    for(i=n/2;i>=1;i++)  // 循环建立初始堆
        sift(R,i,n);
    for(i=n;i>=2;i--)  // 进行n-1次循环,完成堆排序
    {
        swap(R[1],R[i]);  // R[1]→R[i]
        sift(R,1,i-1);  //  筛选R[1]结点,得到i-1个结点的堆
    }
}

9、归并排序:

void merge(int A[],int u,int m,int v)
{
    int i,j,k,t,B[N+1];
    i=u;j=m+1;k=u;
    while(i<=m && j<=v)
        if(A[i]<=A[j])
            B[k++]=A[i++];
        else
            B[k++]=A[j++];
    while(i<m) 
        B[k++]=A[i++];
    while(i<v) 
        B[k++]=A[j++];
    for(i=u;i<=v;i++)
        A[i]=B[i];
}
void merge_Sort(int A[],int low,int high)
{
    int mid;
    if(low<high) /*序列元素个数超过2个*/
    {
        mid=(low+high)/2;
        merge_Sort(A,low,mid); /*递归归并排序左段*/
        merge_Sort(A,mid+1,high); /*递归归并排序右段*/
        merge(A,low,mid,high); /*归并左右段*/
    {
}

10、基数排序:

linklist RadixSort(linklist A)
{
    linklist fr[R],re[R]; /*建立R个桶队列,分别记录队首和队尾*/
    int i,j,K;
    for(i=D-1;i>=0;i--){ /*从最低位关键字开始*/
        for(j=0;j<R;j++)
            fr[j] = re[j] = NULL; /*初始化*/
        while(A){ /*将关键字逐一分配到桶*/
            K=A->key[i]; /*取出当前关键字位*/
            if(!fr[K]) fr[K] = A; /*放入空桶*/
            else re[K]->next = A; /*否则放入桶尾*/
            re[K]=A; /*更新尾指针*/
            A=A->next;
    }
        for(j=R-1;i>=0;j--){
            /*将所有桶中元素收集串起来*/
            if(fr[j]){ /*桶非空*/
                re[j]->next = A;
                A = fr[j];
            }
        }
    }
    return A;
}

小结

  • 14
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
回答:对于数据结构算法的学习,有几本经典的书籍供选择。根据引用内容,有三本书被提及。首先是《数据结构算法分析(c语言描述版)》,这本书被推荐为容易理解且代码实现采用C语言的版本。对于初学者来说,这本书可能是一个不错的选择。其次是《大话数据结构》,这本书在班级里被多人推荐,并被赞为不错的书籍。然而,我无法提供关于这本书的具体评价,因为没有引用内容提供关于它的详细信息。 最后是《算法(第四版)》,这本书采用Java语言实现算法,并使用大量图片演示算法,给人一种友好的感觉。然而,它被认为不是入门书籍,建议在学习之前具备一定的算法基础。所以,最适合你的书籍取决于你的个人需求和背景知识。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [【干货数据结构算法该如何正确学习?(书籍\视频\网站都推荐了)](https://blog.csdn.net/m0_37907797/article/details/103202911)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* [【数据结构算法】如何学习数据结构算法 ?过来人的建议(一)【方法篇】](https://blog.csdn.net/u011074149/article/details/118371293)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值