841软件工程专业综合代码题(1)—— 线性表

本文详细探讨了考研中常见的线性表操作,包括顺序表逆置的朴素实现、双指针法处理负数排序、顺序表插入算法、链表插入和删除,以及针对408真题的特定顺序表问题解决方案。通过实例代码演示,提升考研者对数据结构的理解和应用能力。
摘要由CSDN通过智能技术生成

考研中线性表相关代码题

1、顺序表的逆置问题

image-20221016164232431

SmartSelect_20221016_171440_Samsung Notes
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JWuASA21-1666151784325)(C:\Users\索半斤\Desktop\研究生\blog\images\SmartSelect_20221016_171902_Samsung Notes.jpg)]

image-20221016172131209

image-20221016175336508

image-20221016175358027

上面的算法基于一种比较朴素的思考方式,假如说原序列是1、2、3、4、5、6,那么我们循环左移2位以后就是3、4、5、6、1、2,那么它其实就相当于是将前n位按原顺序移动到数组后面,同时将后面的元素按原顺序移动到前面。那么我们只需要借助一个辅助数组就可以完成,只是空间复杂度会比较高。

image-20221016175914902

2、使用双指针移动元素

将数组中所有的负数移动到前面

这种题实际上也是一类题,我们可以通过双指针的方法进行元素置换,比如说,1、2、3、4、5、-1、-2,那我们可以设置一个指向开头的指针left,然后设置一个只想末尾的指针right。然后同时判断left和right的元素值,如果left值大于0,而right的值小于0,那么我们交换两者的位置同时right–,left++;如果right值大于0而left值小于0则直接right–,left++;如果right值小于0而left值也小于0,则left++,right不变,如果right值大于0而left也大于0,则right–,left不变。

public static void change(int[] array){
    int left = 0;
    int right = array.length-1;
    while(left<right){
        int n1 = array[left];
        int n2 = array[right];
        if(n1 > 0 && n2 > 0 ){
            left++;
            right--;
        }else if(n1>0 && n2 <0){
            array[left] = n2;
            array[right] = n1;
        }else if(n1<0 && n2<0){
            left++;
        }else if(n1<0&&n2>0){
            right--;
        }
    }

}

3、顺序表的插入算法考察

在这里插入图片描述

public static void insertElem(int[] array,int m,int n){
    //遍历后n个元素,以方便将后n个元素插入到前面
    for (int i = m; i < m+n; i++) {
        //将当前位置元素存入临时变量
        int temp = array[i];
        int j;
        //从当前位置元素的前一个元素开始向前遍历,查找插入位置,也就是当找到比当前元素小的元素时,就插入到这个找到的元素后面
        for (j = i-1; j >=0 && temp<array[j] ; j--) {
            //将元素后移,方便插入元素
            array[j+1] = array[j];
        }
        //将当前位置元素插入到合适的位置
        array[j+1] = temp;
    }
}

4、考察链表相关的插入、删除算法

在这里插入图片描述

public static void lickNode(Link l1,Link l2){
    Link p = l1.next;
    Link q = l2.next;
    //设置前一个结点,默认指向l1的头节点,这个节点的作用:因为我们遍历链表时只能遍历到当前节点,所以需要设置指向前一个节点的节点
    Link pre = l1;
    //p和q在遍历过程中都不能为null
    while(p != null && q != null){
        if (p.value < q.value){
            //如果p节点的值小于q节点的值,那么将p赋值给前置节点,然后p节点向后移动
            pre = p;
            p = p.next;
        } else if (p.value > q.value) {
            //如果p节点的值大于q节点的值,那么直接将q节点后移
            q = q.next;
        } else{
            //如果相等,则需要将p中当前的节点删除掉
            pre.next = p.next;
            p = p.next;
        }
    }
}

image-20221018110503284

方法一 建立一个新链表,通过头插法将原链表中的元素插入新链表中,那么倒数第k个也就成了在新链表中查找正数第k个

public static int findNode(Link link,int k){
    Link newLink = new Link();
    Link head = link.next;
    while(head != null){
        Link temp = newLink.next;
        newLink.next = new Link();
        newLink.next.value = head.value;
        newLink.next.next = temp;
        head = head.next;
    }
    for (int i = 0; i < k && newLink != null; i++) {
        head = newLink.next;
        newLink = newLink.next;
    }
    if (head != null){
        System.out.println(head.value);
        return 1;
    }
    return 0;
}

方法二 我们发现,如果要找倒数第k个,那么我们需要从头节点向后移动n-k+1次(n为除头节点外的节点总数),那么我们可以先遍历一遍链表得到节点总数,然后我们可以根据公式在正向遍历链表查找想要的结果。

public static int findNode(Link link,int k){
    Link head = link.next;
    int sum = 0;
    while(head != null){
        sum++;
        head = head.next;
    }
    head = link;
    for (int i = 0;i<sum-k+1 && head != null;i++){
        head = head.next;
    }
    if (head != null){
        System.out.println(head.value);
        return 1;
    }
    return 0;
}

方法三 我们可以设置两个指针,初始化时两个指针first、last都指向头节点,随后设置一个变量step,我们判断步长是否为k,如果不为k,那么就不断向后移动last,如果为k,那么我们向后移动first,如果last已经为空,则遍历结束。

public static int findNode(Link link,int k){
    Link first = link;
    Link last = link;
    int step = 0;
    while(last!= null){
        //一开始step为0,所以在step==k之前一直是last向后移动,随后last和first同时向后并保持step距离
        if (step == k){
            first = first.next;
            step = step-1;
        }else{
            last = last.next;
            step++;
        }
    }
    if (first != null){
        System.out.println(first.value);
        return 1;
    }
    return 0;
}

5、408真题中的顺序表考题

image-20221018155316777

方法一 双层暴力循环

public static void findMainElem(int[] arrays){
    int n = arrays.length;
    for (int i = 0;i<n;i++){
        int m = 1;
        for (int j = i+1; j < n; j++) {
            if (arrays[i] == arrays[j])m++;
        }
        if (m > n/2){
            System.out.println(arrays[i]);
            return;
        }
    }
    System.out.println(-1);
}

方法二

image-20221018165723184

public static void findMainElem02(int[] arrays){
    int c = 0;
    int sum = 0;
    int n = arrays.length;
    for (int i = 0; i < n; i++) {
        if (sum == 0){
            c = arrays[i];
            sum++;
        }else{
            if (c == arrays[i])sum++;
            else sum--;
        }
    }
    sum = 0;
    for (int i = 0; i < n; i++) {
        if (arrays[i] == c)sum++;
    }
    if (sum > n/2){
        System.out.println(c);
    }else{
        System.out.println(-1);
    }

}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

索半斤_suobanjin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值