SCAU数据结构OJ题目第一章题目汇总
文章目录
- 前言
- [8576 顺序线性表的基本操作](#8576 顺序线性表的基本操作)
- [8577 合并顺序表](#8577 合并顺序表)
- [8578 顺序表逆置](#8578 顺序表逆置)
- [8579 链式线性表的基本操作](#8579 链式线性表的基本操作)
- [8580 合并链表](#8580 合并链表)
- [19080 反转链表](#19080 反转链表)
- 总结
前言
数据结构OJ习题第一章内容,有一些用到了C++,因为C++兼容C,所以建议创建cpp文件,OJ编译时选择g++
8576 顺序线性表的基本操作
编写算法,创建初始化容量为LIST_INIT_SIZE的顺序表T,并实现插入、删除、遍历操作。本题目给出部分代码,请补全内容。
输入格式 测试样例格式说明:
根据菜单操作:
1、输入1,表示要实现插入操作,紧跟着要输入插入的位置和元素,用空格分开
2、输入2,表示要实现删除操作,紧跟着要输入删除的位置
3、输入3,表示要输出顺序表的所有元素
4、输入0,表示程序结束
输入样例 1
1 2
1
1 3
2
1
3
0
输出样例 A Sequence List Has Created.
1:Insert element
2:Delete element
3:Load all elements
0:Exit
Please choose:
The Element 2 is Successfully Inserted!
1:Insert element
2:Delete element
3:Load all elements
0:Exit
Please choose:
The Element 3 is Successfully Inserted!
1:Insert element
2:Delete element
3:Load all elements
0:Exit
Please choose:
The Element 3 is Successfully Deleted!
1:Insert element
2:Delete element
3:Load all elements
0:Exit
Please choose:
The List is: 2
1:Insert element
2:Delete element
3:Load all elements
0:Exit
Please choose:
代码如下:
c
#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 struct
{
int *elem;
int length;
int listsize;//最大长度length
}SqList;
int InitList_Sq(SqList &L)
{
// 算法2.3,构造一个空的线性表L,该线性表预定义大小为LIST_INIT_SIZE
// 请补全代码
L.elem = new ElemType[LIST_INIT_SIZE];//new操作符不需要头文件
if(!L.elem)
//exit(ERROR);
return ERROR;
L.length = 0;
L.listsize = LIST_INIT_SIZE;
return OK;
}
int Load_Sq(SqList &L)
{
// 输出顺序表中的所有元素
int i;
if(L.length == 0) printf("The List is empty!"); // 请填空
else
{
printf("The List is: ");
for(i = 0;i<L.length;i++) printf("%d ",L.elem[i]); // 请填空
}
printf("\n");
return OK;
}
int ListInsert_Sq(SqList &L,int i,int e)//注意下标是从0开始的,第一个位置就是L.elem[0]
{
// 算法2.4,在顺序线性表L中第i个位置之前插入新的元素e
// i的合法值为1≤i≤L.length +1
// 请补全代码
if( (i<1)||(i>L.length+1) )
return ERROR;
// if(L.length==LIST_INIT_SIZE)return ERROR;//可加可不加
for(int j = L.length-1; j>=i-1; j--)
{
L.elem[j+1] = L.elem[j];
}
L.elem[i-1] = e;
++L.length;
return OK;
}
int ListDelete_Sq(SqList &L,int i, int &e)//下标从0开始
{
// 算法2.5,在顺序线性表L中删除第i个位置的元素,并用e返回其值
// i的合法值为1≤i≤L.length
// 请补全代码
if( (i<1)||(i>L.length) )//2注意不是i>L.length+1
return ERROR;
e = L.elem[i-1];
for(int j = i; j<=L.length-1; j++)//这个也可以通过
{
L.elem[j-1] = L.elem[j];
}
// for(int j = i-1; j<L.length; j++)//可以通过
// {
// L.elem[j] = L.elem[j+1];
// }
--L.length;
return OK;
}
int main()
{
SqList T;
int a, i;
ElemType e, x;
if(InitList_Sq(T)) // 判断顺序表是否创建成功
{
printf("A Sequence List Has Created.\n");
}
while(1)
{
printf("1:Insert element\n2:Delete element\n3:Load all elements\n0:Exit\nPlease choose:\n");
scanf("%d",&a);
switch(a)
{
case 1: scanf("%d%d",&i,&x);
if( ListInsert_Sq(T,i,x) == ERROR ) printf("Insert Error!\n");
else printf("The Element %d is Successfully Inserted!\n", x);
break;
case 2: scanf("%d",&i);
if( ListDelete_Sq(T,i,e) == ERROR ) printf("Delete Error!\n");
else printf("The Element %d is Successfully Deleted!\n", e);
break;
case 3: Load_Sq(T);
break;
case 0: return 1;
}
}
}
8577 合并顺序表
若线性表中数据元素相互之间可以比较,且数据元素在表中按值递增或递减,则称该表为有序表。
编写算法,将两个非递减有序顺序表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
代码如下:
c
#include<stdio.h>
#include<malloc.h>
#include<iostream>
#define OK 1
#define ERROR 0
#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10
#define ElemType int
typedef struct
{
int *elem; //存储空间基址
int length; //当前长度
int listsize; //当前分配的容量(以sizeof(ElemType)为单位)
}SqList;
int InitList_Sq(SqList &L)
{
L.elem=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));//返回首地址
if(!L.elem) return ERROR; //分配存储失败
L.length=0; //空表长度为0
L.listsize=LIST_INIT_SIZE; //初始存储容量
return OK;
}
int intput_Sq(SqList &L,int n)
{
int i,x;
for(i=0;i<n;i++)
{
scanf("%d",&x);
L.elem[i]=x;
L.length++;
}
return OK;
}
void MergeList_Sq(SqList LA,SqList LB,SqList &LC)
{
int *pa,*pb,*pc,*pa_last,*pb_last;
pa=LA.elem; pb=LB.elem; //指针pa和pb的初值分别指向两个表的第一个元素
LC.length=LA.length+LB.length; //新表长度为待合并两表的长度之和
LC.elem=new ElemType[LC.length]; //为合并后的新表分配一个数组空间
pc=LC.elem; //指针pc指向新表的第一个元素
pa_last=LA.elem+LA.length-1; //指针pa_last指向LA表的最后一个元素
pb_last=LB.elem+LB.length-1; //指针pb_last指向LB表的最后一个元素
while(pa<=pa_last && pb<=pb_last)
{ //两个表都非空
if(*pa<=*pb) *pc++=*pa++; //依次"摘取"两表中值较小的结点
else *pc++=*pb++;
}
while(pa<=pa_last) *pc++=*pa++; //LB表已到达表尾
while(pb<=pb_last) *pc++=*pb++; //LA表已到达表尾
}
void output_Sq(SqList L)//输出
{
int i;
for(i=0;i<L.length;i++)
{
printf("%d ",L.elem[i]);
}
}
int main()
{
SqList LA,LB,LC;
int a,b;
scanf("%d",&a);//输入LA表的元素个数;
InitList_Sq(LA);//创建LA表
intput_Sq(LA,a);//输入LA表元素
scanf("%d",&b);//输入LB表的元素个数;
InitList_Sq(LB);//创建LB表
intput_Sq(LB,b);//输入LB表元素
InitList_Sq(LC);
printf("List A:");
output_Sq(LA);
printf("\n");
printf("List B:");
output_Sq(LB);
printf("\n");
printf("List C:");
MergeList_Sq(LA,LB,LC);//合并两表
output_Sq(LC);
return 0;
}
8578 顺序表逆置
顺序表的基本操作代码如下:
#include<stdio.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)
{ // 算法2.3
// 构造一个空的线性表L。
L.elem = (ElemType )malloc(LIST_INIT_SIZE sizeof(ElemType));
if (!L.elem) return OK; // 存储分配失败
L.length = 0; // 空表长度为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;
}
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;
}
设有一顺序表A=(a0,a1,..., ai,...an-1),其逆顺序表定义为A'=( an-1,..., ai,...,a1, a0)。
设计一个算法,将顺序表逆置,要求顺序表仍占用原顺序表的空间。
输入格式
第一行:输入顺序表的元素个数
第二行:输入顺序表的各元素,用空格分开
输出格式
第一行:逆置前的顺序表元素列表
第二行:逆置后的顺序表元素列表
输入样例
10
1 2 3 4 5 6 7 8 9 10
输出样例
The List is:1 2 3 4 5 6 7 8 9 10
The turned List is:10 9 8 7 6 5 4 3 2 1
代码如下:
c
#include<stdio.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)
{ // 算法2.3
// 构造一个空的线性表L。
L.elem = (ElemType *)malloc(LIST_INIT_SIZE*sizeof(ElemType));
if (!L.elem) return ERROR; // 存储分配失败
L.length = 0; // 空表长度为0
L.listsize = LIST_INIT_SIZE; // 初始存储容量
return OK;
} // InitList_Sq
int input_Sq(SqList &L,int n)//n是个数
{
int x;
for(int i=0;i<n;i++)
{
scanf("%d",&x);
L.elem[i]=x;
L.length++;
}
return OK;
}
int exchange_Sq(SqList &L1,SqList &L2)//将L1数据逆序放入L2
{
int i=L1.length-1,j=0;
while(j<L1.length)
{
L2.elem[j]=L1.elem[i];
j++;i--;
L2.length++;
}
return OK;
}
void output_Sq(SqList L)//输出顺序表
{
int i;
for(i=0;i<L.length;i++)
{
printf("%d ",L.elem[i]);
}
}
int main()
{
SqList L1,L2;
int n;
scanf("%d",&n);
InitList_Sq(L1);//创建L1
input_Sq(L1,n);//输入L1
InitList_Sq(L2);//创建L2
exchange_Sq(L1,L2);//将L1数据逆序放入L2
printf("The List is:");
output_Sq(L1);
printf("\n");
printf("The turned List is:");
output_Sq(L2);
return 0;
}
8579 链式线性表的基本操作
编写算法,创建一个含有n个元素的带头结点的单链表L并实现插入、删除、遍历操作。本题目提供部分代码,请补全内容。
输入格式
测试样例格式说明:
根据菜单操作:
1、输入1,表示要实现插入操作,紧跟着要输入插入的位置和元素,用空格分开
2、输入2,表示要实现删除操作,紧跟着要输入删除的位置
3、输入3,表示要输出顺序表的所有元素
4、输入0,表示程序结束
输入样例
3
3 6 9
3
1
4 12
2
1
3
0
输出样例
Please input the init size of the linklist:
Please input the 3 element of the linklist:
A Link List Has Created.
The LinkList is:3 6 9
1:Insert element
2:Delete element
3:Load all elements
0:Exit
Please choose:
The LinkList is:3 6 9
1:Insert element
2:Delete element
3:Load all elements
0:Exit
Please choose:
The Element 12 is Successfully Inserted!
1:Insert element
2:Delete element
3:Load all elements
0:Exit
Please choose:
The Element 3 is Successfully Deleted!
1:Insert element
2:Delete element
3:Load all elements
0:Exit
Please choose:
The LinkList is:6 9 12
1:Insert element
2:Delete element
3:Load all elements
0:Exit
Please choose:
代码如下:
c
#include<stdio.h>
#include<malloc.h>
#define ERROR 0
#define OK 1
#define ElemType int
typedef struct LNode
{
int data;
struct LNode *next;
} LNode,*LinkList;
int CreateLink_L(LinkList &L,int n)
{
// 创建含有n个元素的单链表
LinkList p,q;
int i;
ElemType e;
L = new LNode;
L->next = NULL; // 先建立一个带头结点的单链表
q = L;
for (i=0; i<n; i++)
{
scanf("%d", &e);
p = new LNode; // 生成新结点
// 请补全代码
p->data = e;
p->next = NULL;
q->next = p;
q = q->next;
}
return OK;
}
int LoadLink_L(LinkList &L)
{
// 单链表遍历
LinkList p = L->next;
if(p == NULL)printf("The List is empty!"); // 请填空
else
{
printf("The LinkList is:");
while(p != NULL) // 请填空
{
printf("%d ",p->data);
p = p->next; // 请填空
}
}
printf("\n");
return OK;
}
int LinkInsert_L(LinkList &L,int i,ElemType e)
{
// 算法2.9
// 在带头结点的单链线性表L中第i个位置之前插入元素e
// 请补全代码
LinkList p = L,s;//p指向头结点
int j=0;
while( p && (j<i-1) )
{
p=p->next;
j++;
}
if(!p||j>i-1) return ERROR;
s=new LNode;
s->data=e;
s->next=p->next;
p->next=s;
return OK;
}
int LinkDelete_L(LinkList &L,int i, ElemType &e)
{
// 算法2.10
// 在带头结点的单链线性表L中,删除第i个元素,并用e返回其值
// 请补全代码
LinkList p = L,q;
int j=0;
while( p->next && (j<i-1) )
{
p=p->next;
j++;
}//找第i个,p指向其前驱
if( !(p->next) || (j>i-1) ) return ERROR;
q=p->next;
p->next=q->next;//跳过要删除的元素
e=q->data;
delete q;
return OK;
}
int main()
{
LinkList T;
int a,n,i;
ElemType x, e;
printf("Please input the init size of the linklist:\n");
scanf("%d",&n);
printf("Please input the %d element of the linklist:\n", n);
if( CreateLink_L(T,n) == OK ) // 判断链表是否创建成功,请填空
{
printf("A Link List Has Created.\n");
LoadLink_L(T);
}
while(1)
{
printf("1:Insert element\n2:Delete element\n3:Load all elements\n0:Exit\nPlease choose:\n");
scanf("%d",&a);
switch(a)
{
case 1:
scanf("%d%d",&i,&x);
if(LinkInsert_L(T,i,x) == ERROR) printf("Insert Error!\n"); // 判断i值是否合法,请填空
else printf("The Element %d is Successfully Inserted!\n", x);
break;
case 2:
scanf("%d",&i);
if(LinkDelete_L(T,i,e) == ERROR) printf("Delete Error!\n"); // 判断i值是否合法,请填空
else printf("The Element %d is Successfully Deleted!\n", e);
break;
case 3:
LoadLink_L(T);
break;
case 0:
return 1;
}
}
}
8580 合并链表
线性链表的基本操作如下:
#include<stdio.h>
#include<malloc.h>
#define ERROR 0
#define OK 1
#define ElemType int
typedef int Status;
typedef struct LNode
{
int data;
struct LNode *next;
} LNode,*LinkList;
Status ListInsert_L(LinkList &L, int i, ElemType e) // 算法2.9
{
// 在带头结点的单链线性表L的第i个元素之前插入元素e
LinkList p,s;
p = L;
int j = 0;
while (p && j < i-1) // 寻找第i-1个结点
{
p = p->next;
++j;
}
if (!p || j > i-1) return ERROR; // i小于1或者大于表长
s = (LinkList)malloc(sizeof(LNode)); // 生成新结点
s->data = e;
s->next = p->next; // 插入L中
p->next = s;
return OK;
} // LinstInsert_L
Status ListDelete_L(LinkList &L, int i, ElemType &e) // 算法2.10
{
// 在带头结点的单链线性表L中,删除第i个元素,并由e返回其值
LinkList p,q;
p = L;
int j = 0;
while (p->next && j < i-1) // 寻找第i个结点,并令p指向其前趋
{
p = p->next;
++j;
}
if (!(p->next) || j > i-1) return ERROR; // 删除位置不合理
q = p->next;
p->next = q->next; // 删除并释放结点
e = q->data;
free(q);
return OK;
} // ListDelete_L
设计一个算法将两个非递减有序链表A和B合并成一个新的非递减有序链表C。
输入格式
第一行:单链表A的元素个数
第二行:单链表A的各元素(非递减),用空格分开
第三行:单链表B的元素个数
第四行:单链表B的各元素(非递减),用空格分开
输出格式
第一行:单链表A的元素列表
第二行:单链表B的元素列表
第三行:合并后单链表C的元素列表
输入样例
6
12 24 45 62 84 96
4
15 31 75 86
输出样例
List A:12 24 45 62 84 96
List B:15 31 75 86
List C:12 15 24 31 45 62 75 84 86 96
代码如下:
c
#include<malloc.h>
#include<stdio.h>
#include<iostream>
#define ERROR 0
#define OK 1
#define Elemtype int
//#define int Status
typedef int Status;
using namespace std;
typedef struct LNode
{
Status data;
struct LNode* next;
}LNode,*Linklist;
Elemtype Initlist(Linklist &L,Elemtype n)//注意用指针来接收LA
{
Elemtype i = 0;
L = new LNode;//一定要记得创建空间
Linklist p = L,q;//带有头结点
L->next = NULL;
while(i<n)
{
Elemtype elem;
scanf("%d",&elem);
q = new LNode;
q->data = elem;
q->next = NULL;
p->next = q;
p = p->next;
i++;//
}
return OK;
}
void mergelist(Linklist LA,Linklist LB,Linklist &LC)
{
LC = new LNode;
LC->next = NULL;
Linklist pa = LA->next,pb = LB->next,pc = LC;
while(pa&&pb)
{
if(pa->data<=pb->data)
{
pc->next = pa;
// if(pa->data == pb->data)
// {
// pb = pb->next;
// }//注意相等的两个数字也要输出,因为非递减
pa = pa->next;
pc = pc->next;
}
else
{
pc->next = pb;
pb = pb->next;
pc = pc->next;
}
}
if(!pa)
{
while(pb)
{
pc->next = pb;
pb = pb->next;
pc = pc->next;
}
}
if(!pb)
{
while(pa)
{
pc->next = pa;
pa = pa->next;
pc = pc->next;
}
}
//pc->next = NULL;
}
void print(Linklist L)
{
Linklist p = L->next;
printf("%d",p->data);
p = p->next;
while(p != NULL)
{
printf(" %d",p->data);
p = p->next;
}
}
int main()
{
Linklist LA,LB,LC;//LNode
int na,nb;
//cin>>na;
scanf("%d",&na);
Initlist(LA,na);
printf("List A:");
print(LA);
printf("\n");
scanf("%d",&nb);
Initlist(LB,nb);
printf("List B:");
print(LB);
printf("\n");
mergelist(LA,LB,LC);
printf("List C:");
print(LC);
return 0;
}
19080 反转链表
给定一个单链表的头结点L,长度为n,反转该链表后,返回新链表的表头。
要求:空间复杂度 O(1) ,时间复杂度 O(n)。
如当输入链表{1,2,3}时,经反转后,原链表变为{3,2,1},所以对应的输出为{3,2,1}。
输入格式
第一行一个整数n,代表链表长度。
第二行n个整数。
输出格式
输出逆置后的单链表。
输入样例
5
1 2 3 4 5
输出样例
5 4 3 2 1
代码如下:
c
#include <iostream>
using namespace std;
struct LNode
{
int data;
LNode * next;
};
void createList(LNode * &L,int n)
{
/*< 尾插法创建单链表 */
LNode *r, *p;
r=L=new LNode;/*< 创建头结点 */
L->next=NULL;
for(int i=1; i<=n; i++)
{
p=new LNode;
cin>>p->data;
p->next=NULL;
r->next=p;
r=p;
}
}
void trv(LNode * L)
{
/*< 一个简单的链表遍历函数,供编程过程中测试使用 */
L=L->next;
while(L)
{
cout<<L->data<<' ';
L=L->next;
}
}
void reverseList(LNode * &L)
{
LNode *pre = NULL;/*< 用三个指针分别表示前驱,当前,后继 */
LNode *cur = L->next;/*< 当前是第一个节点a1 */
LNode *nex = NULL; /*<思考如何用这三个指针实现翻转,另外,三个指针也要同步后移 */
while (cur)
{
//_______________________
pre = cur;
cur = cur->next;
pre->next = nex;
nex = pre;
}
L->next=pre;//让头结点指向原来链表的最后一个节点
}
int main()
{
int n;
LNode *L;
cin>>n;
createList(L,n);
reverseList(L);
trv(L);
return 0;
}
总结
之前刚开始学的时候感觉很难,现在看感觉挺简单的,加油!