(1) 定义顺序表结构,并实现顺序表的建立,并输出顺序表的全部结点值(遍历)。(顺序表的建立和遍历为在顺序表上的运算,用自定义函数实现)
(2)在题目一的基础上实现如下算法:设计一个高效的算法,从有序顺序表L中删除所有值介于x和y之间的所有元素,要求时间复杂度为O(n)。(顺序表中元素类型为int)
(3)在题目一的基础上实现如下算法:已知顺序表L中的元素为int,请写一时间复杂度为O(n)、空间复杂度为O(1)的算法,将L中的奇数元素排在前面,偶数元素排在后面
(4)在题目一的基础上实现如下算法:编写算法,在一非递减的顺序表L中,删除所有值相等的多余元素。要求时间复杂度为O(n),空间复杂度为O(1);
(5)在题目一的基础上实现如下算法:实现顺序表的就地逆置算法,即在原表的存储空间将线性表(a1,a2,a3,…,an)逆置为(an,an-1,an-2,…,a1)。
问题1:我们用结构体定义一个顺序表,并让其具有重置和输入输出功能
具体实现如下:较为简单就不分析代码实现过程
typedef struct{//结构体变量
int elem[MAXSIZE];
int last;
}SeqList;
void chushihualist(SeqList *L){//格式化表
L-> last= - 1;
}
void chuangjianlist(SeqList *L){//创建表
int n,i=0;
printf("输入数据表长度n:");
scanf("%d",&n);
printf("输入%d个元素:\n",n);
while(i<n){
scanf("%d",&L->elem[i]);
i++;
}
L->last=n-1;
}
问题二:删除顺序表内一定范围的元素:
在这里我们首先遍历所有元素,并判断顺序表的的元素是否至少为2个,然后定义一个int变量k=0用来记录介于x到y之间的元素,每发现一个我们K++;然后我们让[i-k]=[i],直接覆盖掉介于x到y间的元素;其次我们还需重置顺序表下标last让其不输出多余元素。然后我们调用输出函数将其输出。其满足时间复杂度O(n).
oid shanchux_y(SeqList *L)//删除介于x到y间的函数。
{
int x,y,s;
printf("请输入删除元素范围");
scanf("%d %d",&x,&y);
int k=0;
if(x>=y||L->last==0)
s=0;
else
{
for(int i=0;i<=L->last;i++)
{
if(L->elem[i]>x&&L->elem[i]<y)
k++;
else
L->elem[i-k]=L->elem[i];
}
}
L->last=(L->last)-k;
s=1;
if(s==1)
{
printf("删除范围%d到%d后顺序表为\n",x,y);
shuchulist(*L);
}
}
问题三:奇前偶后排序
在这里我们使用双指针,一个指针指向第一个元素,一个指针指向最后一个元素,然后交换奇数偶数的位置,直到两指针相遇。
void swap(int *a,int *b)
{
int t=*a;
*a=*b;
*b=t;
}
void jioupaixu(SeqList *L)//将奇数排在前面偶数排在后面。
{
int i=0,j=L->last;
while(i<j){
while(i<j&&L->elem[i]%2==1)i++;
while(i<j&&L->elem[j]%2==0)j--;
if(i<j)swap(&L->elem[i],&L->elem[j]);
}
printf("奇偶排序后顺序表为:\n");
shuchulist(*L);
}
问题4:非递减数中删除多余等值元素
首先解释一下非递减数及后面的数要求大于或等于前面的数eg:1 2 2 3 3;非递增反之。
可以使用双指针的方法来实现。定义两个指针阅和j,初始时i=0,j=1。从头开始遍历顺序表,如果a[i]和a中相等,则j++;否则将a[]赋值给a[i+1](在这里我们定义一个int k=0,让其记录赋值次数方便重置表长),i++,j++。最后将i+1赋值给表长即可。最后重置表长
void shanchudengzhi(SeqList *L)//在非递减数列中删除等值多余元素
{
int i=0,j=1,k=0;
if(L->last==-1||L->last==0){
printf("无法删除!");
return;
}
else{
while(j<=L->last){
if(L->elem[i]==L->elem[j])
j++;
else{
L->elem[++i]=L->elem[j++];
}
}
while(i<=L->last-1){
L->elem[++i]=0;
k++;
}
L->last=L->last-k;
}
printf("删除等值多余数后顺序表为:\n");
shuchulist(*L);
}
问题5;逆置输出
我们将表从中对折让元素第一位和最后一位交换,第二位和倒数第二位交换......以此类推,随着程序的执行i++,自然而然的交换到中间元素,较简单读者自行理解
void nizhilist(SeqList *L)//逆置输出
{
int i,t;
if(L->last>=1){
for(i=0;i<(L->last+1)/2;i++)
{
t=L->elem[i];
L->elem[i]=L->elem[L->last-i];
L->elem[L->last-i]=t;
}
printf("逆置元素后表中的元素为:\n");
shuchulist(*L);}
else{
printf("无法逆置!\n");
return;
}
}
全局代码;
在主函数中使用switch语句每个case语句调用一个函数解决问题,再使用while使之不断运行,并打印一个菜单增强可读性。
int main(void)
{
int choice;
SeqList L;
while(1){
menu();
printf("请选择菜单:");
scanf("%d",&choice);
if(choice==0) break;
switch(choice){
case 4:chushihualist(&L);break;
case 1:chuangjianlist(&L);break;
case 2:shuchulist(L);break;
case 3:shanchux_y(&L);break;
case 5:jioupaixu(&L);break;
case 6:shanchudengzhi(&L);break;
case 7:nizhilist(&L);break;
default:printf("输入错误!请重新输入\n");
}
}return 0;
}
全部代码实现
#include<stdio.h>
#define MAXSIZE 100
void menu()
{
printf("1.创建表 2.输出表\n");
printf("3.删除范围 4.初始化表格\n");
printf("5.奇偶排序 6.删除多余数\n");
printf("7.逆置顺序表 0.退出\n");
}
typedef struct{
int elem[MAXSIZE];
int last;
}SeqList;
void chushihualist(SeqList *L){//格式化表
L-> last= - 1;
}
void chuangjianlist(SeqList *L){//创建表
int n,i=0;
printf("输入数据表长度n:");
scanf("%d",&n);
printf("输入%d个元素:\n",n);
while(i<n){
scanf("%d",&L->elem[i]);
i++;
}
L->last=n-1;
}
void shuchulist(SeqList L){//输出表
int i;
if(L.last==-1)
printf("表空!");
for(i=0;i<=L.last;i++)
printf(" %d",L.elem[i]);
printf("\n");
}
void shanchux_y(SeqList *L)//删除介于x到y间的函数。
{
int x,y,s;
printf("请输入删除元素范围");
scanf("%d %d",&x,&y);
int k=0;
if(x>=y||L->last==0)
s=0;
else
{
for(int i=0;i<=L->last;i++)
{
if(L->elem[i]>x&&L->elem[i]<y)
k++;
else
L->elem[i-k]=L->elem[i];
}
}
L->last=(L->last)-k;
s=1;
if(s==1)
{
printf("删除范围%d到%d后顺序表为\n",x,y);
shuchulist(*L);
}
}
void swap(int *a,int *b)
{
int t=*a;
*a=*b;
*b=t;
}
void jioupaixu(SeqList *L)//将奇数排在前面偶数排在后面。
{
int i=0,j=L->last;
while(i<j){
while(i<j&&L->elem[i]%2==1)i++;
while(i<j&&L->elem[j]%2==0)j--;
if(i<j)swap(&L->elem[i],&L->elem[j]);
}
printf("奇偶排序后顺序表为:");
shuchulist(*L);
}
void shanchudengzhi(SeqList *L)//在非递减数列中删除等值多余元素
{
int i=0,j=1,k=0;
if(L->last==-1||L->last==0){
printf("无法删除!");
return;
}
else{
while(j<=L->last){
if(L->elem[i]==L->elem[j])
j++;
else{
L->elem[++i]=L->elem[j++];
}
}
while(i<=L->last-1){
L->elem[++i]=0;
k++;
}
L->last=L->last-k;
}
printf("删除等值多余数后顺序表为:\n");
shuchulist(*L);
}
void nizhilist(SeqList *L)//逆置输出
{
int i,t;
if(L->last>=1){
for(i=0;i<(L->last+1)/2;i++)
{
t=L->elem[i];
L->elem[i]=L->elem[L->last-i];
L->elem[L->last-i]=t;
}
printf("逆置元素后表中的元素为:\n");
shuchulist(*L);}
else{
printf("无法逆置!\n");
return;
}
}
int main(void)
{
int choice;
SeqList L;
while(1){
menu();
printf("请选择菜单:");
scanf("%d",&choice);
if(choice==0) break;
switch(choice){
case 4:chushihualist(&L);break;
case 1:chuangjianlist(&L);break;
case 2:shuchulist(L);break;
case 3:shanchux_y(&L);break;
case 5:jioupaixu(&L);break;
case 6:shanchudengzhi(&L);break;
case 7:nizhilist(&L);break;
default:printf("输入错误!请重新输入\n");
}
}return 0;
}