【趣学C语言和数据结构100例】66-70

简介: 本书《趣学C语言和数据结构100例》精选了5个典型的数据结构问题及C语言实现,涵盖链表与数组操作,如有序集合的集合运算、有序序列表的合并、数组中两顺序表位置互换、三递增序列公共元素查找及奇偶数重排。通过详细解析与代码示例,帮助读者深入理解数据结构与算法设计的核心思想,提升编程技能。

【趣学C语言和数据结构100例】

问题描述

66.已知递增有序的单链表 A,B,C分别存储了一个集合,设计算法实现 A=AU(B-C),要求单链表仍然有序。

67.将两个有序顺序表合并为一个新的有序顺序表,并由函数返回结果顺序表。

68.已知在一维数组 A[m+n]中依次存放两个线性表(a1,a2,a3,…,am)和(b1,b2,b3.…,bn)。编写一个函数,将数组中两个顺序表的位置互换,即将(b1,b2,b3.…,bn)放在(a1,a2,a3,…,am)的前面。

69.给定三个序列 A、B、C,长度均为 n,且均为无重复元素的递增序列,请设计一个时|上尽可能高效的算法,逐行输出同时存在于这三个序列中的所有元素。例如,数组 A为{1.2.3],数组 B为{2.3,4],数组C为{-1,0.2},则输出 2

70.已知线性表按顺序存储,且每个元素都是不相同的整型元素,设计把所有的奇数移动至偶数前面的算法。

代码分析

==66.有序的单链表 A,B,C->A=AU(B-C)==
思路:先实现B-C,并保存在B中,然后AUB。

具体分析:传入3个链表,返回链表,对ABC都操作,则函数名为:LiukList 函数名(LiukList &A,LiukList &B,LiukList &C);

1.先实现B-C,定义pre记录B的p所到的位置,使p和分别指向B和C,两个使用while循环遍历,使他们两个值小的进行移动,到值相等。在相等时,使pre即此刻的p的前一个指向p的下一个,即跳过p,并且释放p,令p更新为现在的pre的下一个。

2.然后AUB,p和q指向A和B的头部开始,定义r作为辅助记录A的前一个,两个使用while循环遍历,如果p的值小,r更新为p,并且使用尾插法将q插入,并且更新r的位置到p,使p向后移动继续比较。如果q的值小,r更新为q,并且使用将q插入,并且更新r的位置到q,使q向后移动继续比较。直到结束,返回链表A。

==67.两个有序顺序表->新的有序顺序表==

//顺序表的数据结构
typedef struct {
   
    DataType *data;         // 数据数组
    int length;             // 当前长度
    int capacity;           // 容量
} SeqList;

分析:合并成功返回1,合并失败返回0。输入3个顺序表,AB用来参数,C用来记录合并后的数据。故函数名为:bool 函数名(SeqList A,SeqList B,SeqList C);如果A+B的长度>C的长度,则直接返回false,定义i,j,k,i为访问A,j为访问B,k为访问C,在不到最后时,使A.data[i]和B.data[j]小的存在C中,并且对应的k++和i++。在比较结束后,使i<长度,或j<长度,的把剩下的存入C中。返回1即可。

==68.将数组中两个顺序表的位置互换==
思路:先整体反转,再b1到bn反转,使a1到am反转。

具体分析:传入一个数组A[],以及n和m,还有数组的大小。先反转0到m+n-1反转,然后0到n-1反转,然后n到m+n-1反转,故一个调用。everse(A,0,m+n-1,m+n); everse(A,0,n-1,n); everse(A,n,m+n-1,m);接下来写 everse函数。输入函数A,以及左右边值,还有大小。故函数名为void everse(DataType A[],int left,int right,int arrsize),如果左<0 或者 左>右 或者 右>数组大小,即出现失误,则返回return 0。当左<右时,进行左右值的交换,并且令左++,右--,即可完成交换。

==69.输出同时存在于这三个序列 A、B、C中的共同元素==
分析:传入abc3个数组和数组的大小n,故函数名为void func(int a[],int b[],int c[],int n),定义i,j,k分别访问3个数组,当3个都<n时开始访问。如果3个的值相等,则输出a中的值,否则查找。先找到3个中最大的数,再<它的后进行++,直到找到3个的值相等时进行输出。

==70.线性表把所有的奇数移动至偶数前面==
分析:采用双指针,即左右同时,定义一个high和low,初始化为length-1和0。使用temp记录第一个的值,使用while循环遍历,再 low < high情况子下, 找到偶数: high 指针向左移动,直到找到一个奇数。把这个奇数的值给了low的奇数。从low开始,找到奇数: low 指针向右移动,直到找到一个偶数。把这个偶数的值给了high的偶数。重复: 重复步骤 1-3,直到 low 和 high 指针相遇。最后再把之前的temp的值还回去。

代码实现

#include<stdio.h>
int main(){
   
//    66.已知递增有序的单链表 A,B,C分别存储了一个集合,设计算法实现 A=AU(B-C),要求单链表仍然有序。
Linklist fun(Linklist &A,Linklist &B,Linklist &C){
   
    //B-C
    Lnode *pre=B,*p=B->next,*q=C->next;
    while(p && q){
   
        if(p->data<q->data){
   
            pre=p;
            p=p->next
        }else if(p->data>q->data){
   
            q=q->next;
        }else{
   
            pre->next=p->next;
            free(p);
            p=pre->next;
        }

    }
    //AUB
    p=A->next;
    q=B->next;
    Lnode *r=A;  //为行动 
    A->next=NULL;
    while(p && q){
   
        if(p->data<q->data){
   
            r->next=p;
            r=p;
            p=p->next
        }else {
   
            r->next=q;
            r=q;
            q=q->next
        }
    }
    if(p==NULL){
   
        r->next=q;
    }else{
   
        r->next=p;
    }
    return A; 
}    

//    67.将两个有序顺序表合并为一个新的有序顺序表,并由函数返回结果顺序表
bool func(seqlist A,seqlist B,seqlist C){
   
    if(A.lenth+B.lenth>C.lenth){
   
        return 0;
    }
    int i=0,j=0,k=0;
    while(i<A.lenth && i<b.lenth){
   
        if(A.data[i]<=B.data[j]){
   
            C.data[k++]=A.data[i++];
        }else{
   
            C.data[k++]=B.data[j++];
        }
    }
    while(i<A.lenth){
   
        C.data[k++]=A.data[i++];
    }
    while(i<B.lenth){
   
        C.data[k++]=B.data[j++];
    }    
    C.length=k;
    return 1;
}

//    68.已知在一维数组 A[m+n]中依次存放两个线性表(a1,a2,a3,…,am)和(b;,bz,b.…,bn)。编写一个函数,将数组中两个顺序表的位置互换,即将(bi,b,,b;,,…,b)放在(a1,a2,a3,…,am)的前面。
typedef int DataType;
void everse(DataType A[],int left,int right,int arrsize){
   
    if(left>=right  || right > arrsize){
   
        return 0;
    }
    if(left<0){
   
        return 0;
    }
    int mid=(left+right)/2;
    while(left<right){
   
        DataType teap=A[left];
        A[left]=A[right];
        A[right]=teap;
        left++;
        right--;
    }
}

void func(DataType A[],int m,int n,int arrarise){
   
    everse(A,0,m+n-1,m+n);
    everse(A,0,n-1,n);
    everse(A,n,m+n-1,m);

}

//    69.给定三个序列 A、B、C,长度均为 n,且均为无重复元素的递增序列,请设计一个时|上尽可能高效的算法,逐行输出同时存在于这三个序列中的所有元素。例如,数组 A为{1.2.3],数组 B为{2.3,4],数组C为{-1,0.2},则输出 2
int max(int a,int b,int c){
   
    if(b>a){
   
        a=b;
    }
    if(c>a){
   
        a=c;
    }
    return a;
}
void func(int a[],int b[],int c[],int n){
   
    int i=0,j=0,k=0;
    while(i<n && j<n && k<n){
   
        if(a[i]==b[j] && a[i]==c[k]){
   
            printf("%d ",a[i]);
        }else{
   
            int maxnum=max(a[i],b[j],c[k]);
            if(a[i]<maxname){
   
                i++;
            }
            if(b[j]<maxname){
   
                j++;
            }
            if(c[k]<maxname){
   
                k++;
            }    
        }    
    }
}

//    70.已知线性表按顺序存储,且每个元素都是不相同的整型元素,设计把所有的奇数移动至偶数前面的算法。
void func(int a[],int len){
   
    int low=0,high=len-1;
    int temp=a[low];
    while(low<high){
   
        while(low<high && a[high]%2==0){
   
            high--;
        }
        a[low]=a[high];
        while(low<high && a[low]%2==0){
   
            low++;
        }
        a[high]=a[low];
    }
    a[low]=temp;
}



    return 0;
}

总结

本文介绍了五个数据结构问题及其C语言实现,这些问题涉及链表和数组的操作,包括有序集合的集合运算、有序序列表的合并、数组中两个顺序表的位置互换、三个递增序列的公共元素查找以及奇偶数的重新排列。这些算法不仅在理论上具有重要意义,而且在实际应用中也非常广泛。

有序集合的集合运算问题要求我们将三个有序单链表进行集合运算,实现A=AU(B-C)。这个问题的解决关键在于正确地遍历链表并根据条件将节点分配到不同的链表中,同时保持链表的有序性。

有序序列表的合并问题要求我们将两个有序序列表合并为一个新的有序序列表。这个问题可以通过比较两个序列表的元素并按顺序插入到新序列表中来解决。

数组中两个顺序表的位置互换问题要求我们在一维数组中交换两个顺序表的位置。这个问题可以通过整体反转数组、然后分别反转两个子数组来实现。

三个递增序列的公共元素查找问题要求我们找出三个无重复元素的递增序列中的公共元素。这个问题可以通过三指针法来高效解决,即同时遍历三个数组,找到公共元素。

奇偶数的重新排列问题要求我们将线性表中的所有奇数移动至偶数前面,同时保持元素的相对顺序。这个问题可以通过双指针法来解决,即同时从数组的两端开始遍历,交换奇偶数。

这些算法的实现不仅展示了C语言在处理链表和数组时的能力,也体现了算法设计的基本思想,如指针操作、条件判断和循环控制。通过这些算法的学习,我们可以更好地理解数据结构和算法的基本概念,提高解决实际问题的能力。

总的来说,这些算法问题不仅锻炼了编程能力,也加深了对数据结构和算法的理解。通过这些问题的解决,我们可以逐步提高自己的编程技能,为将来的学习和工作做好准备。这些算法的掌握对于计算机专业的学生和软件开发人员来说都是非常重要的。通过这些练习,我们可以逐步提高自己的编程技能,为将来的学习和工作做好准备。

目录
相关文章
|
3天前
|
机器学习/深度学习 算法 C语言
【趣学C语言和数据结构100例】11-15
本文介绍了五个C语言编程问题及其实现,包括矩阵对角线元素之和、有序数组插入、数组逆序、杨辉三角输出和魔方阵生成。每个问题不仅涉及基本的数组操作,还涵盖了算法设计的核心思想,如循环、条件判断和递归。通过解决这些问题,读者可以加深对C语言和数据结构的理解,提升编程技能。这些问题的解决过程展示了如何有效处理数组和矩阵,以及如何利用算法优化程序性能,为实际应用提供了宝贵的实践经验。
25 4
【趣学C语言和数据结构100例】11-15
|
3天前
|
存储 机器学习/深度学习 搜索推荐
【趣学C语言和数据结构100例】86-90
本文介绍并用C语言实现了五种经典排序算法:直接插入排序、折半插入排序、冒泡排序、快速排序和简单选择排序。每种算法都有其特点和适用场景,如直接插入排序适合小规模或基本有序的数据,快速排序则适用于大规模数据集,具有较高的效率。通过学习这些算法,读者可以加深对数据结构和算法设计的理解,提升解决实际问题的能力。
21 4
|
3天前
|
存储 算法 数据处理
【趣学C语言和数据结构100例】81-85
本文介绍了五个经典算法问题及其C语言实现,涵盖图论与树结构的基础知识。包括使用BFS求解单源最短路径、统计有向图中入度或出度为0的点数、统计无向无权图各顶点的度、折半查找及二叉排序树的查找。这些算法不仅理论意义重大,且在实际应用中极为广泛,有助于提升编程能力和数据结构理解。
21 4
|
3天前
|
存储 算法 C语言
【趣学C语言和数据结构100例】1-5
《趣学C语言和数据结构100例》精选5个编程问题,涵盖数学计算、字符串处理、数列求和等领域。通过求解最大公约数与最小公倍数、字符统计、特殊数列求和、阶乘求和及分数数列求和,不仅锻炼编程技巧,还加深对算法和数据结构的理解。每个问题均附有详细的代码实现,帮助读者掌握C语言的核心概念和技术。
27 4
|
3天前
|
存储 算法 C语言
【趣学C语言和数据结构100例】51-55
本文介绍了五个关于链表操作的C语言实现案例,包括删除单链表中的重复元素、从两个有序链表中查找公共元素、判断一个链表是否为另一链表的连续子序列、判断循环双链表是否对称及合并两个循环单链表。每个案例都详细解析了算法思路与实现方法,涵盖了链表操作的多种场景,旨在帮助读者深入理解链表数据结构的应用,提升算法设计与编程能力。
21 4
|
3天前
|
存储 算法 搜索推荐
【趣学C语言和数据结构100例】91-95
本文涵盖多个经典算法问题的C语言实现,包括堆排序、归并排序、从长整型变量中提取偶数位数、工人信息排序及无向图是否为树的判断。通过这些问题,读者可以深入了解排序算法、数据处理方法和图论基础知识,提升编程能力和算法理解。
22 4
|
3天前
|
存储 算法 vr&ar
【趣学C语言和数据结构100例】71-75
本文介绍了五个C语言数据结构问题及其实现,涵盖链表与二叉树操作,包括按奇偶分解链表、交换二叉树左右子树、查找节点的双亲节点、计算二叉树深度及求最大关键值。通过递归和遍历等方法,解决了理论与实际应用中的常见问题,有助于提升编程能力和数据结构理解。
19 4
|
3天前
|
存储 算法 C语言
【趣学C语言和数据结构100例】16-20
本文精选了五个C语言编程问题,涵盖数组操作、字符串处理等基础领域。包括查找二维数组中的鞍点、折半查找法、统计文章中字符数量、电文解密及字符串连接。每个问题都附有详细的代码实现与分析,旨在帮助读者理解算法逻辑,提升编程技巧。通过这些实践,不仅能锻炼编程能力,还能加深对数据结构和算法的理解,为未来的学习和工作打下坚实基础。
35 4
|
3天前
|
算法 数据可视化 数据建模
【趣学C语言和数据结构100例】76-80
本文介绍了五种图论算法的C语言实现,涵盖二叉树的层次遍历及广度优先搜索(BFS)和深度优先搜索(DFS)的邻接表与邻接矩阵实现。层次遍历使用队列按层访问二叉树节点;BFS利用队列从源节点逐层遍历图节点,适用于最短路径等问题;DFS通过递归或栈深入图的分支,适合拓扑排序等场景。这些算法是数据结构和算法学习的基础,对提升编程能力和解决实际问题至关重要。
22 4
|
3天前
|
存储 算法 C语言
【趣学C语言和数据结构100例】26-30
本文精选五个编程问题,涵盖递归、数字处理、字符串操作、组合数学和数论等领域,通过C语言实现,旨在提升编程能力和算法理解。包括递归逆序打印字符、正整数位数及逆序打印、回文数判断、0-7组成奇数个数计算及偶数分解为两素数之和。
18 4
【趣学C语言和数据结构100例】26-30