线性表-课后习题01-08

0301 从顺序表中删除具有最小值的元素(假设唯一)并由函数返回被删元素的值,空出的位置由最后一个元素填补。若顺序表为空,则显示出出错信息并退出运行。

思路:函数中用引用型参数key返回删除的最小值的元素值。首先判断顺序表是否为空,为空直接返回。若不为空,首先赋值key为顺序表第一个元素值 ,定义新变量pos,记录删除的元素值的位置。for循环遍历顺序表,若元素值小于等于key,就将元素值赋给key,最后,key中保存了删除的最小元素值。在循环外面,用最后的元素值填补删除的元素值位置,顺序表长度减1。

算法代码:

bool deletemin(SqList &L,ElemType &key) {
    if(L.length==0) {
        return false;
    }
    key=L.data[0];
    int pos=0;
    for(int i=0; i<L.length; i++) {
        if(L.data[i]<=k)
            k=L.data[i];
        pos=i;
    }
    L.data[pos]=L.data[L.length-1];
    L.length--;
    return true;
}

运行代码:

#include<iostream>
#include<string>
#define Max 50    //表长度的初始定义 
using namespace std;
//定义一个 顺序表
struct SqList {
	int data[Max]= {1,2,3,4,5,6,7,8};
	int length=8;
};
bool deletemin(SqList &L,int &k) {
	if(L.length==0) {
		return false;
	}
	int min=L.data[0];
	int pos=0;
	for(int i=0; i<L.length; i++) {
		if(L.data[i]<=min){
			min=L.data[i];
			pos=i;
		}
	}
	k=min; 
	L.data[pos]=L.data[L.length-1];
//	L.length--;
	return true;
}
int main() {
	SqList s;	//定义顺序表s
	int value=0;
	cout<<"删除最小值前的顺序表为:"<<endl;
	for(int i=0; i<s.length; i++) {
		cout<<s.data[i]<<" ";
	}
	cout<<endl;
	if(deletemin(s,value)) {
		cout<<"删除的元素为:"<<value<<endl;
		cout<<"删除最小值后的顺序表为:"<<endl;
		for(int j=0; j<s.length; j++) {
			cout<<s.data[j]<<" ";
		}
	} else
		cout<<"错误"<<endl;
	return 0;
}

运行结果

 02 设计一个高效算法,将顺序表的所有元素逆置,要求算法的空间复杂度为O(1)。

思路:算法的空间复杂度为O(1),即在当前存储空间上操作。for循环遍历顺序表,L.Length/2为中间点,首先,key存储左侧的元素值,右侧的元素值搬到左侧,右侧的位置存放之前存储在key的元素值。

算法代码:

bool reverse(SqList &L) {
    int key=L.data[0]; 
    for(int i=0; i<L.length/2; i++) {
        key=L.data[i];
        L.data[i]=L.data[L.length-(i+1)];
        L.data[L.length-(i+1)]=key;
    }
}

运行代码:

#include<iostream>
#include<string>
#define Max 50    //表长度的初始定义 
using namespace std;
//定义一个 顺序表
struct SqList {
	int data[Max]= {1,2,3,4,5,6,7,8};
	int length=8;
};
bool reverse(SqList &L) {
	int key=L.data[0]; 
	for(int i=0; i<L.length/2; i++) {
		key=L.data[i];
		L.data[i]=L.data[L.length-(i+1)];
		L.data[L.length-(i+1)]=key;
	}
}
int main() {
	SqList s;	//定义顺序表s
	int value=0;
	cout<<"逆置前的顺序表为:"<<endl;
	for(int i=0; i<s.length; i++) {
		cout<<s.data[i]<<" ";
	}
	cout<<endl;
	reverse(s) ;
	for(int i=0; i<s.length; i++) {
		cout<<s.data[i]<<" ";
	}
	return 0;
}

 运行结果

03 对长度为n的顺序表L,编写一个时间复杂度为O(n),空间复杂度为O(1)的算法,该算法删除线性中所有值为x的数据元素。

思路1:循环遍历顺序表,顺序表中的元素分为与x相等、与x不相等两种。可以挑选出不相等数据元素放在一个新数组中,但是因为空间复杂度为O(1),只能选择在原数组中操作。对于不等于x的元素,依次放在数组中,并且用k记录数量,同时k也是对应元素的位置下标。

算法代码:

void deletex(SqList &L,ElemType x) {
    int k=0,i;
    for(int i=0; i<L.length; i++) {
        if(L.data[i]!=x) {
            L.data[k]=L.data[i];
            k++;
        } 
    }
    L.length=k;
}

运行代码: 

#include<iostream>
#include<string>
#define Max 50    //表长度的初始定义 
using namespace std;
//定义一个 顺序表
struct SqList {
	int data[Max]= {1,2,3,4,5,6,7,8};
	int length=8;
};
void deletex(SqList &L,int x) {
	int k=0,i;
	for(int i=0; i<L.length; i++) {
		if(L.data[i]!=x) {
			L.data[k]=L.data[i];
			k++;
		} 
	}
	L.length=k;
}
int main() {
	SqList s;	//定义顺序表s
	int value=0;
	cout<<"删除前的顺序表为:"<<endl;
	for(int i=0; i<s.length; i++) {
		cout<<s.data[i]<<" ";
	}
	cout<<endl;
	deletex(s,2) ;
	cout<<"删除后的顺序表为:"<<endl;
	for(int i=0; i<s.length; i++) {
		cout<<s.data[i]<<" ";
	}
	return 0;
}

 运行结果

思路2:循环遍历顺序表,并且用k记录与x相等的元素个数。在相等元素之后遇到的不相等元素前移动k个元素的位置。比如a[2]==x;a[3]!=x; a[4]==x;a[5]!=x; 遇到a[2]后把它删除,a[3]移动一个位置填补到a[2]的位置。遇到a[4]删除,k变成2,此时,a[3]a[4]的位置都是空的,a[5]移动两个位置填补到原来a[3]的位置。

算法代码:

void deletex(SqList &L,int x) {
    int k=0;
    while(i<L.length) 
        if(L.data[i]==x) {
            k++;
        } 
        else{
            L.data[i-k]=L.data[i];
        } 
        i++; 
    }
    L.length=L,length-k;

04 从有序顺序表中删除其值在给定值s与t 之间(要求s<t)的所有元素,若s或T不合理活顺序表为空,则显示出错误信息并退出运行。

思路:有序顺序表说明数据元素是有序排列的,属于s-t范围的数据元素在一片区域内,可以先找到小于s的元素个数i,再找到小于等于t元素个数j,依次移动,将位置j的元素赋给i位置j的元素。

算法代码:

bool deletescope(SqList &L,ElemType s,ElemType t) {
    int i=0;
    int j=0; 
    if(s>t||L.length==0) 
        return false; 
    while(L.data[i]<s) 
        i++;
    while(L.data[j]<=t) 
        j++ ;
    for(;j<L.length;i++,j++) {
        L.data[i]=L.data[j] ;
    }
    L.length=i;
    return true; 
}

 运行代码:

#include<iostream>
#include<string>
#define Max 50    //表长度的初始定义 
using namespace std;
//定义一个 顺序表
struct SqList {
	int data[Max]= {1,2,3,4,5,6,7,8};
	int length=8;
};
bool deletescope(SqList &L,int s,int t) {
	int i=0;
	int j=0; 
	if(s>t||L.length==0) 
		return false; 
	while(L.data[i]<s) 
		i++;
	while(L.data[j]<=t) 
		j++ ;
	for(;j<L.length;i++,j++) {
		L.data[i]=L.data[j] ;
	}
	L.length=i;
	return true; 
}
int main() {
	SqList s;	//定义顺序表s
	int value=0;
	cout<<"删除前的顺序表为:"<<endl;
	for(int i=0; i<s.length; i++) {
		cout<<s.data[i]<<" ";
	}
	cout<<endl;
	deletescope(s,2,5) ;
	cout<<"删除后的顺序表为:"<<endl;
	for(int i=0; i<s.length; i++) {
		cout<<s.data[i]<<" ";
	}
	return 0;
}

运行结果:

05 从顺序表中删除其值在给定值s与t 之间(包含s和t,要求s<t)的所有元素,若s或t不合理活顺序表为空,则显示出错误信息并退出运行。

思路:循环遍历顺序表,用k计数在s到t范围的元素的数据元素个数,若属于范围内,则k+1,若不属于该范围内,则向前移动k个位置。最后顺序表的长度减少k。

算法代码:

bool deletescope2(SqList &L,ElemType s,ElemType t) {

    int k=0; 
    if(s>=t||L.length==0) 
        return false; 
    for(int i=0;i<L.length;i++) {
        if(L.data[i]>=s&&L.data[i]<=t) 
            k++; 
        else
            L.data[i-k]=L.data[i]; 
    }
    L.length=L.length-k;
    return true; 
}

运行代码:

#include<iostream>
#include<string>
#define Max 50    //表长度的初始定义 
using namespace std;
//定义一个 顺序表
struct SqList {
	int data[Max]= {1,2,3,4,5,6,7,8};
	int length=8;
};
bool deletescope2(SqList &L,int s,int t) {
	if(s>t||L.length==0) 
		return false; 
	int k=0; 
	for(int i=0;i<L.length;i++) {
		if(L.data[i]>=s&&L.data[i]<=t) 
			k++; 
		else
			L.data[i-k]=L.data[i]; 
	}
	L.length=L.length-k;
	return true; 
}
int main() {
	SqList s;	//定义顺序表s
	int value=0;
	cout<<"删除前的顺序表为:"<<endl;
	for(int i=0; i<s.length; i++) {
		cout<<s.data[i]<<" ";
	}
	cout<<endl;
	deletescope2(s,2,5) ;
	cout<<"删除后的顺序表为:"<<endl;
	for(int i=0; i<s.length; i++) {
		cout<<s.data[i]<<" ";
	}
	return 0;
}

 运行结果:

06 从有序顺序表中删除所有其值重复的元素,使表中所有元素的值不同。

思路1:循环遍历顺序表,若当前元素与下一元素相等,则计数k+1,若不相等,则向前移动k个元素,最后k记录了重复元素的重复次数,顺序表长度减去k。

算法代码:

bool deletesame(SqList &L) {
    int k=0;

    if(L.length==0)

        return false;
    for(int i=0; i<L.length; i++) {
        if(L.data[i]==L.data[i+1])
            k++;
        else
            L.data[i-k]=L.data[i];
    }
    L.length=L.length-k;

    return true;
}

运行代码:

 

#include<iostream>
#include<string>
#define Max 50    //表长度的初始定义 
using namespace std;
//定义一个 顺序表
struct SqList {
	int data[Max]= {1,2,2,3,3,3,4,4};
	int length=8;
};
void deletesame(SqList &L) {
	int k=0;
	for(int i=0; i<L.length; i++) {
		if(L.data[i]==L.data[i+1])
			k++;
		else
			L.data[i-k]=L.data[i];
	}
	L.length=L.length-k;
}
int main() {
	SqList s;	//定义顺序表s
	int value=0;
	cout<<"删除前的顺序表为:"<<endl;
	for(int i=0; i<s.length; i++) {
		cout<<s.data[i]<<" ";
	}
	cout<<endl;
	deletesame(s) ;
	cout<<"删除后的顺序表为:"<<endl;
	for(int i=0; i<s.length; i++) {
		cout<<s.data[i]<<" ";
	}
	return 0;
}

运行结果:

 

 思路2:第一个元素无论与后面元素是否重复,都不会被删除。比较后面的元素与第一个元素是否相等,若相等,继续判断,若不想等,将其插入第一个元素后面。一直向后判断,比较后面的元素与前面不重复的最后一个元素是否相等。

算法代码:

bool deletesame(SqList &L) {
    int i,j;

    if(L.length==0)

        return false;
    for(i=0,j=1; j<L.length; j++) {
        if(L.data[i]!=L.data[j])
            L.data[++i]=L.data[j];
    }
    L.length=i+1;

    return true;
}

07 将两个有序顺序表合并为一个新的有序顺序表,并由函数返回结果顺序表。

思路:比较A,B两个顺序表中的元素,将较小的头结点放入新的顺序表C中。当其中一个全部放入时,另外一个可将剩余部分全部放入C的后面。

算法代码:

bool merge(SqList A,SqList B,SqList &C) {
    if(A.length+B.length>C.maxSize)
        return false;
    int i=0;
    int j=0;
    int k=0;
    while(i<A.length&&j<B.length) { //当其中一个表先遍历结束,就跳出循环
        if(A.data[i]<=B.data[j]) 
            C.data[k++]=A.data[i++];  //输入的时候,直接就是0,不用看后面循环+1的,先执行一遍,再加1

         else 
            C.data[k++]=B.data[j++];
    }
    while(i<A.length)
        C.data[k++]=A.data[i++];
    while(j<B.length)
        C.data[k++]=B.data[j++];
    C.length=k;
    return true;
}

  运行代码:

#include<iostream>
#include<string>
#define Max 50    //表长度的初始定义 
using namespace std;
//定义一个 顺序表
struct SqList {
	int data[Max];
	int length;
};
bool merge(SqList A,SqList B,SqList &C) {
	if(A.length+B.length>C.length)
		return false;
	int i=0;
	int j=0;
	int k=0;
	while(i<A.length&&j<B.length) { //当其中一个表先遍历结束,就跳出循环
		if(A.data[i]<=B.data[j]) 
			C.data[k++]=A.data[i++];
		 else 
			C.data[k++]=B.data[j++];
	}
	while(i<A.length)
		C.data[k++]=A.data[i++];
	while(j<B.length)
		C.data[k++]=B.data[j++];
	C.length=k;
	return true;
}

int main() {
	SqList A= {{2,3,4,6,7},5};
	SqList B= {{3,4,4},3};;	//定义顺序表s
	SqList C;
	C.length=8;
	cout<<"合并前的顺序表为:"<<endl;
	for(int i=0; i<A.length; i++) {
		cout<<A.data[i]<<" ";
	}
	cout<<endl;
	for(int i=0; i<B.length; i++) {
		cout<<B.data[i]<<" ";
	}
	cout<<endl;
	merge(A,B,C);
	cout<<"合并后的顺序表为:"<<endl;
	for(int i=0; i<C.length; i++) {
		cout<<C.data[i]<<" ";
	}
	return 0;
}

运行结果:

 08 已知在一维数组A[m+n]中依次存放两个线性表(a1,a2,......am)和(b1,b2,......bn)。编写一个函数,将数组中两个顺序表的位置互换,即将(b1,b2,......bn)放在(a1,a2,......am)前面。

思路:首先将整个顺序表逆置,然后分别对0-n-1和n-m+n-1分别逆置。

算法代码:

void reverse(SqList &L,ElemType left,ElemType right) {
    int key=0;
    int mid=(left+right)/2;
    for(int i=0; i<=mid-left; i++) {
        key=L.data[left+i];
        L.data[left+i]=L.data[right-i];
        L.data[right-i]=key;
    }
}
void exchange(SqList &L,ElemType m,ElemType n){
    reverse(L,0,m+n-1);
    reverse(L,0,m-1);
    reverse(L,n,m+n-1);
}

运行代码:

#include<iostream>
#include<string>
#define Max 50    //表长度的初始定义 
using namespace std;
//定义一个 顺序表
struct SqList {
	int data[Max]={1,2,3,4,5,6,7,8};
	int length=8;
};
void reverse(SqList &L,int left,int right) {
	int key=0;
	int mid=(left+right)/2;
	for(int i=0; i<=mid-left; i++) {
		key=L.data[left+i];
		L.data[left+i]=L.data[right-i];
		L.data[right-i]=key;
	}
}
void exchange(SqList &L,int m,int n){
	reverse(L,0,m+n-1);
	reverse(L,0,m-1);
	reverse(L,n,m+n-1);
}
int main() {
	SqList s;
	cout<<"逆置前的顺序表为:"<<endl;
	for(int i=0; i<s.length; i++) {
		cout<<s.data[i]<<" ";
	}
	cout<<endl;
	exchange(s,4,4);
	cout<<"逆置后的顺序表为:"<<endl;
	for(int i=0; i<s.length; i++) {
		cout<<s.data[i]<<" ";
	}
	return 0;
}

运行结果:

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值