1、用 SqList 类型自行建立两个有序的顺序表,然后将其合并成一个新的有序表(即实现算法2.7)。

#include <stdio.h>
#include <stdlib.h>
#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10
#define OK 1
#define OVERFLOW 0
#define ERROR 0
//目标: 顺序表的合并
typedef struct{
    int *elem; //数据元素
    int length; //元素长度
    int listsize; //存储空间大小
} SqList;

//初始化顺序表L
int InitList_Sq(SqList* L){
    L->elem = (int*)malloc(LIST_INIT_SIZE * sizeof(int));
    if( !L->elem )exit( OVERFLOW );
    L->length = 0; //元素长度为 0
    L->listsize = LIST_INIT_SIZE; //分配初始存储空间
    return OK;
}

//获取表中第 i 个位置元素,储存到 e
//void GetElem(SqList L, int i, int *e){
//    *e = *(L.elem + i - 1);
//}

//获取表中元素长度
int ListLength(SqList L){
    return L.length;
}

//扩容表的存储容量,每次增加 10 个数据的容量
void ListExpand(SqList* L){
    int* newbase = (int*)malloc((L->listsize + LISTINCREMENT)*sizeof(int));
    L->elem = newbase;
    L->listsize += LISTINCREMENT;
}

//在表L中第 i 个位置插入新的元素 e ,L元素长度加 1
void ListInsert(SqList* L, int i, int e){
    *(L->elem + i - 1) = e;
    L->length++;
}

//判断输入的数据是否非递减
void DataJudge(SqList L){
    for(int m=0; m<L.length-1; m++){
        if(L.elem[m] > L.elem[m+1]){
            printf("输入数据有误,请核对后按非递减顺序输入。\n");
            exit(ERROR);
        }
    }
}

//合并两个顺序表
void MergeList_Sq(SqList La, SqList Lb, SqList *Lc){
    //具体可实现:
    //已知的顺序表La,Lb中,元素按非递减顺序排列
    //归并La和Lb至Lc中,Lc仍然按非递减顺序排列
    int *pa = La.elem, *pb = Lb.elem; //定义两个操作指针
    
    Lc->listsize = Lc->length = ListLength(La) + ListLength(Lb); //Lc元素长度、储存空间赋值
    int *pc = Lc->elem = (int*)malloc(Lc->listsize * sizeof(int));//Lc操作指针
    if( !Lc->elem )exit(OVERFLOW); //内存分配失败
    
    int *pa_last = La.elem + ListLength(La) - 1; //顺序表末地址
    int *pb_last = Lb.elem + ListLength(Lb) - 1;
    
    //合并
    while(pa<=pa_last && pb<=pb_last){
        if(*pa <= *pb) *pc++ = *pa++;
        else *pc++ = *pb++;
    }
    while(pa <= pa_last) *pc++ = *pa++;
    while(pb <= pb_last) *pc++ = *pb++;
}

//输出合并后的顺序表
void PrintMergedList_Sq(SqList* Lc){
    printf("合并后的顺序表元素依次为:");
    for(int m=0; m<Lc->length; m++){
        printf("%d ", Lc->elem[m]);
    }
    printf("\n");
}

int main() {
    SqList La, Lb, Lc;
    
    InitList_Sq(&La);
    InitList_Sq(&Lb);
    InitList_Sq(&Lc);
    
    int len_a = 0, len_b = 0;
    printf("请分别输入顺序表La、Lb的元素长度,以空格键分开:\n");
    scanf("%d %d", &len_a, &len_b);
    
    if(len_a > La.listsize){ //输入元素长度是否溢出
        do{
            ListExpand(&La);
        }while(La.listsize >= len_a);
    }
    if(len_b > Lb.listsize){ //输入元素长度是否溢出
        do{
            ListExpand(&Lb);
        }while(Lb.listsize >= len_b);
    }
    
    int i = 0, e1 = 0;
    printf("请输入顺序表 La 的各元素(非递减顺序):\n");
    while(i<len_a){
        scanf("%d", &e1);
        ListInsert(&La, ++i, e1);
    }
    
    int j = 0, e2 = 0;
    printf("请输入顺序表 Lb 的各元素(非递减顺序):\n");
    while(j<len_b){
        scanf("%d", &e2);
        ListInsert(&Lb, ++j, e2);
    }
    
    DataJudge(La); //判断输入数据是否非递减
    DataJudge(Lb);
    
    MergeList_Sq(La, Lb, &Lc); //合并
    PrintMergedList_Sq(&Lc); //输出
    return 0;
}



运行结果示例:



(输入格式正确的情况)

在这里插入图片描述

(输入格式错误的情况)

在这里插入图片描述


2、用 LinkList 类型自行建立两个有序的单链表,然后将其合并成一个新的有序单链表(即实现算法2.12)。

#include <stdio.h>
#include <stdlib.h>
#define ERROR 0
#define OK 1
//实现将两个单链表 La、Lb 的合并,储存于 La 中
typedef struct LNode{
    int data;
    struct LNode *next;
} LNode, *LinkList;

//初始化 L,分配内存
LinkList InitList_L(LinkList L){
    return (LinkList)malloc(sizeof(LNode));
}

//输入元素,创建链表
void CreatLink_L(LinkList L, int n){
    int temp = 0;
    LinkList p = L;
    while(n--){
        LinkList q = (LinkList)malloc(sizeof(LNode));
        q->next = NULL;
        scanf("%d", &temp);
        q->data = temp;
        p->next = q;
        p = p->next;
    }
}

//输出单链表
void PrintList(LinkList L){
    L = L->next;
    while(L){
        printf("%d ", L->data);
        L = L->next;
    }
    printf("\n");
}

//有序单链表合并
LinkList MergeList_L(LinkList La, LinkList Lb){
    LinkList pa, pb, pc;
    pa = La->next;
    pb = Lb->next;
    pc = La;
    LinkList Lc = pc;
    while(pa && pb){
        if(pa->data <= pb->data){
            pc->next = pa;
            pc = pa;
            pa = pa->next;
        }
        else{
            pc->next = pb;
            pc = pb;
            pb = pb->next;
        }
    }
    pc->next = pa ? pa : pb;
    pc->next->next = NULL;
    return Lc;
}

int main() {
    int m = 0, n = 0;
    LinkList La, Lb, Lc;
    La = InitList_L(La);
    Lb = InitList_L(Lb);
    Lc = InitList_L(Lc);
    
    printf("请分别输入单链表La、Lb的元素个数:\n");
    scanf("%d %d", &m, &n);
    
    printf("请依次输入 La 的元素(非递减顺序):\n");
    CreatLink_L(La, m);
    printf("请依次输入 Lb 的元素(非递减顺序):\n");
    CreatLink_L(Lb, n);
    
    Lc = MergeList_L(La, Lb);
    
    printf("合并后的链表元素依次为:\n");
    PrintList(Lc);
    return 0;
}



运行结果示例:



在这里插入图片描述


3、分别分析有序的顺序表合并,和有序的单链表合并的算法时间复杂度。


答:

  • 假设顺序表La、Lb的元素数量分别为:m、n,单链表La、Lb的元素数量分别为:x、y。
  • 由于算法中,对两个顺序表(单链表)中的元素,在进行相互比较这一操作时,每个元素是否立即插入合并后的新表这个判断语句只被遍历了一遍,故时间复杂度为两个表的元素数量之和。
  • 则:

    顺序表合并的时间复杂度 O(n) = m + n .

    单链表合并的时间复杂度 O(n) = x + y .



版权声明:本文为qq_51971595原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_51971595/article/details/121579482