数据结构HW2

3. (10分) 编程实现一个数组插入算法(源文件命名insert.c),要求在数组a[]的所有奇数下标里插入某个数x。函数定义如下:

int insert_odd (int a[], int n, int x) {

// n是数组的实际长度,在所有<=n的奇数下标a[1], a[3], …里插入x

// a[]的最大长度足够大

// 返回数组的新长度

}

#include <stdio.h>

int insert_odd(int a[], int n, int x) {
    // 检查边界条件和错误情况
    if (n <= 0) {
        printf("错误:数组长度必须是正整数。\n");
        return -1; // 返回-1表示错误
    }

    // 计算新数组的长度
    int new_n = n+n/2;
    

    // 移动奇数下标的元素以腾出空间
    int j = new_n-1;
       for(int i = n-1;i>=0;i--){
            if(i%2!=0){
                a[j] = a[i];
                // 插入新元素x到奇数下标位置
                a[j-1] = x;
                j -= 2;
            }
            else {
            a[j] = a[i];
            j--;
            }
       }
    


    // 返回新数组的长度
    return new_n;
}

int main() {
    // 测试样例
    int a[99] = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21};
    int n = 11; // 数组长度
    int x = 99; // 要插入的数

    printf("原始数组:");
    for (int i = 0; i < n; i++) {
        printf("%d ", a[i]);
    }
    printf("\n");

    int new_n = insert_odd(a, n, x);

    if (new_n != -1) {
        printf("插入后的数组:");
        for (int i = 0; i < new_n; i++) {
            printf("%d ", a[i]);
        }
        printf("\n");
    }

    return 0;
}

4. (10分) 编程实现一个数组的删除算法(源文件命名delete_array.c),要求删除数组a[]的所有x。函数定义如下:

int delete_all (int a[], int n, int x) {

// n是数组的实际长度

// 返回数组的新长度

}

#include<stdio.h>
int delete_all (int a[], int n, int x) {
    int k=0;
        for(int i=0;i<n;i++){
            if(a[i] == x){
                for(int j = i;j<n;j++){
                    a[j] = a[j+1];
                }
                k++;
            }
        }
        n = n-k;
        return n;
    }
int main()
{
    int a[]={1,99,3,99,5,6,7,99,};
    int n=sizeof(a)/sizeof(a[0]); 
	int x=99;
    n = delete_all(a,n,x);

    printf("数组新长度为:%d ",n);
    printf("\n删除 %d 后的数组:\n", x);
    for (int i = 0; i < n; i++) {
        printf("%d ", a[i]);
    }

    printf("\n");
    return 0;

}

5. (10分) 编程实现有重复元素的二分查找,并找到所有目标元素的位置(源文件命名bsearch_duplicate.c),函数定义如下。并给出算法的平均时间复杂度(要写出分析过程)

void bsearch_dup (int a[], int n, int x, int res[]) {

// a[]的前n个元素中寻找x,返回x的最早位置和最晚位置,存在res[]

// 因此,res[]是个只有两个元素的数组。若x不存在,令res=[-1, -1]

// a已经排好序,但可能有重复元素

}

#include <stdio.h>

void bsearch_dup(int a[], int n, int x, int res[]) {
    int first_occurrence = -1; // 初始值表示未找到
    int last_occurrence = -1;  // 初始值表示未找到
    int left = 0;
    int right = n - 1;

    while (left <= right) {
        int mid = left + (right - left) / 2;

        if (a[mid] == x) {
            // 找到x后,更新first_occurrence和last_occurrence
            first_occurrence = mid;
            last_occurrence = mid;

            // 继续在左半部分查找更早的位置
            int left_index = mid - 1;
            while (left_index >= 0 && a[left_index] == x) {
                first_occurrence = left_index;
                left_index--;
            }

            // 继续在右半部分查找更晚的位置
            int right_index = mid + 1;
            while (right_index < n && a[right_index] == x) {
                last_occurrence = right_index;
                right_index++;
            }

            break; // 因为a已排序,不必继续查找
        } else if (a[mid] < x) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }

    res[0] = first_occurrence;
    res[1] = last_occurrence;
}

int main() {
    int a[] = {1, 2, 2, 3, 3, 3, 4, 5, 5, 6};
    int n = sizeof(a) / sizeof(a[0]);
    int x = 3;
    int res[2] = {-1, -1};

    bsearch_dup(a, n, x, res);

    if (res[0] != -1 && res[1] != -1) {
        printf("元素 %d 的最早位置:%d\n", x, res[0]);
        printf("元素 %d 的最晚位置:%d\n", x, res[1]);
    } else {
        printf("元素 %d 不存在。\n", x);
    }

    return 0;
}

6. (10分) 编程实现(带头结点)链表的一个删除算法,要求删除所有等于x的结点(源文件命名delete_linkedlist.c),函数定义如下:

typedef struct Node {

    int data;

    struct Node* next;

} Node;

int delete_all (Node** head, int x){

// head是无用的头结点,删除所有等于x的结点

// 返回删除的结点数目

}

#include <stdio.h>
#include <stdlib.h>

typedef struct Node {
    int data;
    struct Node* next;
} Node;

int delete_all(Node** head, int x) {
    int deleted_count = 0;

    // 处理头结点之后的结点
    Node* current = *head;
    while (current->next != NULL) {
        // 检查下一个结点的数据是否等于x
        if (current->next->data == x) {
            Node* temp = current->next; // 保存要删除的结点
            current->next = current->next->next; // 删除结点
            free(temp); // 释放内存
            deleted_count++;
        } else {
            current = current->next; // 没有删除结点,继续遍历
        }
    }

    return deleted_count;
}

// 打印链表
void print_list(Node* head) {
    Node* current = head->next;
    while (current != NULL) {
        printf("%d -> ", current->data);
        current = current->next;
    }
    printf("NULL\n");
}

// 创建新结点
Node* create_node(int data) {
    Node* new_node = (Node*)malloc(sizeof(Node));
    if (new_node != NULL) {
        new_node->data = data;
        new_node->next = NULL;
    }
    return new_node;
}

int main() {
    // 创建带头结点的链表
    Node* head = create_node(-1); // 头结点
    Node* node1 = create_node(1);
    Node* node2 = create_node(2);
    Node* node3 = create_node(2);
    Node* node4 = create_node(3);

    // 连接结点
    head->next = node1;
    node1->next = node2;
    node2->next = node3;
    node3->next = node4;

    printf("原始链表:\n");
    print_list(head);

    int x = 2;
    int deleted_count = delete_all(&head, x);

    if (deleted_count > 0) {
        printf("删除所有等于 %d 的结点后的链表:\n", x);
        print_list(head);
        printf("删除的结点数目:%d\n", deleted_count);
    } else {
        printf("没有找到等于 %d 的结点。\n", x);
    }

    // 释放链表内存
    Node* current = head;
    while (current != NULL) {
        Node* temp = current;
        current = current->next;
        free(temp);
    }

    return 0;
}

7. (10分) 编程实现(不带头结点)链表反转的递归算法(源文件命名linkedlist_reverse.c),函数定义如下。并给出算法的时间复杂度(要写出分析过程)

Node** reverse (Node** head){

// 返回新的头结点

}

#include <stdio.h>
#include <stdlib.h>

typedef struct Node {
    int data;
    struct Node* next;
} Node;

// 反转链表
Node* reverse(Node* head) {
    if (head == NULL || head->next == NULL) {
        return head; // 如果链表为空或只有一个结点,直接返回
    }

    Node* new_head = reverse(head->next); // 递归反转剩余部分

    // 将当前结点的下一个结点的指针指向当前结点,反转链接
    head->next->next = head;
    head->next = NULL;

    return new_head; // 返回新的头结点
}

// 打印链表
void print_list(Node* head) {
    Node* current = head;
    while (current != NULL) {
        printf("%d -> ", current->data);
        current = current->next;
    }
    printf("NULL\n");
}

// 创建新结点
Node* create_node(int data) {
    Node* new_node = (Node*)malloc(sizeof(Node));
    if (new_node != NULL) {
        new_node->data = data;
        new_node->next = NULL;
    }
    return new_node;
}

int main() {
    // 创建链表
    Node* node1 = create_node(1);
    Node* node2 = create_node(2);
    Node* node3 = create_node(3);
    Node* node4 = create_node(4);

    // 连接结点
    node1->next = node2;
    node2->next = node3;
    node3->next = node4;

    printf("原始链表:\n");
    print_list(node1);

    Node* new_head = reverse(node1);

    printf("反转后的链表:\n");
    print_list(new_head);

    // 释放链表内存
    Node* current = new_head;
    while (current != NULL) {
        Node* temp = current;
        current = current->next;
        free(temp);
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值