8577 合并顺序表
题干
时间限制:1000MS 代码长度限制:10KB
提交次数:5339 通过次数:2251
题型: 编程题 语言: G++
Description
若线性表中数据元素相互之间可以比较,且数据元素在表中按值递增或递减,则称该表为有序表。
编写算法,将两个非递减有序顺序表A和B合并成一个新的非递减有序顺序表C。
输入格式
第一行:顺序表A的元素个数
第二行:顺序表A的各元素(非递减),用空格分开
第三行:顺序表B的元素个数
第四行:顺序表B的各元素(非递减),用空格分开
输出格式
第一行:顺序表A的元素列表
第二行:顺序表B的元素列表
第三行:合并后顺序表C的元素列表
输入样例
5
1 3 5 7 9
5
2 4 6 8 10
输出样例
List A:1 3 5 7 9
List B:2 4 6 8 10
List C:1 2 3 4 5 6 7 8 9 10
提示
输出时注意大小写和标点。
代码实现:
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define OK 1
#define ERROR 0
#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10
#define ElemType int
typedef int Status;
typedef struct
{
int *elem;
int length;//实际长度
int listsize;//存储容量,做检测用,避免长度超过容量
}SqList;
Status InitList_sq(SqList &L)
{
L.elem=new ElemType[LIST_INIT_SIZE];//其实就是表示 数组
if(!L.elem) return OK;
L.length=0;
L.listsize = LIST_INIT_SIZE;
return OK;
}
Status ListInsert_Sq(SqList& L, int i, ElemType e)
{ // 算法2.4
// 在顺序线性表L的第i个元素之前插入新的元素e,
// i的合法值为1≤i≤ListLength_Sq(L)+1
ElemType* p;
if (i < 1 || i > L.length + 1) return ERROR; // i值不合法
if (L.length >= L.listsize) { // 当前存储空间已满,增加容量
ElemType* newbase = (ElemType*)realloc(L.elem,
(L.listsize + LISTINCREMENT) * sizeof(ElemType));
if (!newbase) return ERROR; // 存储分配失败
L.elem = newbase; // 新基址
L.listsize += LISTINCREMENT; // 增加存储容量
}
ElemType* q = &(L.elem[i - 1]); // q为插入位置
for (p = &(L.elem[L.length - 1]); p >= q; --p) *(p + 1) = *p;
// 插入位置及之后的元素右移
*q = e; // 插入e
++L.length; // 表长增1
return OK;
} // ListInsert_Sq
Status ListDelete_Sq(SqList& L, int i, ElemType& e)
{ // 算法2.5
// 在顺序线性表L中删除第i个元素,并用e返回其值。
// i的合法值为1≤i≤ListLength_Sq(L)。
ElemType* p, * q;
if (i<1 || i>L.length) return ERROR; // i值不合法
p = &(L.elem[i - 1]); // p为被删除元素的位置
e = *p; // 被删除元素的值赋给e
q = L.elem + L.length - 1; // 表尾元素的位置
for (++p; p <= q; ++p) *(p - 1) = *p; // 被删除元素之后的元素左移
--L.length; // 表长减1
return OK;
} // ListDelete_Sq
int main()
{
SqList A, B, C;
InitList_Sq(A);
InitList_Sq(B);
InitList_Sq(C);
int a, b, c, each1, each2;
scanf("%d", &a);
for (int i = 0; i < a; i++) {
scanf("%d", &each1);
ListInsert_Sq(A, A.length + 1, each1);
}
printf("List A:");
for (int i = 0; i < A.length; i++) {
printf("%d ", A.elem[i]);
}
printf("\n");
scanf("%d", &b);
for (int j = 0; j < b; j++) {
scanf("%d", &each2);
ListInsert_Sq(B, B.length + 1, each2);
}
printf("List B:");
for (int i = 0; i < B.length; i++) {
printf("%d ", B.elem[i]);
}
printf("\n");
int i = 0, j = 0;
while (i < a && j < b) {
if (A.elem[i] <= B.elem[j]) {
ListInsert_Sq(C, C.length + 1, A.elem[i]);
i++;//当前元素被使用,进入下一位
}
else {
ListInsert_Sq(C, C.length + 1, B.elem[j]);
j++;
}
}
while (i < a) {//此时已不满足j < b
ListInsert_Sq(C, C.length + 1, A.elem[i]);
i++;
}
while (j < b) {
ListInsert_Sq(C, C.length + 1, B.elem[j]);
j++;
}
printf("List C:");
for (int i = 0; i < C.length; i++) {
printf("%d ", C.elem[i]);
}
printf("\n");
return 0;
}
当你写到8578(即下一道题)时就会发现其实除主函数外的函数基本上都有提供。
因此作为基本函数理解算理也非常重要
要知道的几点:
-
顺序表和数组的区别与联系:
(a)线性表采用顺序存储的方式存储就称之为顺序表,顺序表是将表中的结点依次存放在计算机内存中一组地址连续的存储单元中。而数组是从物理存贮的角度来说的,线性表可以用数组存贮也可以用链表来存贮。
(b)可以用一种浅略的观点理解顺序表:带长度(和容量)的数组 -
new 和 newbase
(a)new操作符,即new函数仅仅是用来申请内存空间,不进行其他任何操作,而且针对对象是void*数据类型的指针
(b)newbase:新基址 -
删除算法 和 插入算法 的算法原理
(a)删除:删除第i项—> 被删除元素之后的元素左移 —> 表长减一
(b)插入:i值和容量检测 —>找到插入位置—> 以后元素右移 —>插入表长加一 -
q = L.elem + L.length - 1; 为啥表示表尾元素的位置?
L.elem表示元素存放的首地址,总共是有L.length个元素,由于是最后一个元素,地址即为L.elem + L.length - 1