顺序表课后题2.2.3:
使用的顺序表是
https://blog.csdn.net/killers_999/article/details/104418578
这里。
1.
从顺序表中删除具有最小值的元素(假设唯一 )并由函数返回被删元素的值。 空出的位置由最后一个元素填补, 若顺序表为空则显示出错信息并退出运行。
bool minnum(struct Array *arr,datatype *data){
if(arr->length==0){
return false;
}
else {
(*data)=*(arr->fData);
int posi;
for(int i=1;ilength;i++){
if(*(arr->fData+i)<(*data)){
posi=i;
(*data)=*(arr->fData+i);
}
}
*data=*(arr->fData+posi);
*(arr->fData+posi)=*(arr->fData+(arr->length-1));
arr->length--;
return true;
}
}
2.设计一个高效算法, 将顺序表 L 的所有元素逆置,要求算法的空间复杂度为 o(1)。
void reverse(struct Array *arr){
datatype temp;
for(int i=0;ilength/2;i++){
int right=arr->length-1-i;
temp=*(arr->fData+right);
*(arr->fData+right)=*(arr->fData+i);
*(arr->fData+i)=temp;
}
}
3.对长度为 n 的顺序表 L,编写一个时间复杂度为 O(n)、空间复杂度为 o(1)的算法, 该算法删除线性表中所有值为 x 的数据元素。
void deleteX(struct Array *arr,datatype x){
int k=0;
for(int i=0;ilength;i++){
if(*(arr->fData+i)!=x){
*(arr->fData+i-k)=*(arr->fData+i);
}
else {
k++;
}
}
arr->length-=k;
}
4. 从有序顺序表中删除其值在给定值 s 与 t 之间( 要求 s < t ) 的所有元素, 如果 s 或 f 不合理或顺序表为空,则显示出错信息并退出运行。
bool deleteST(struct Array *arr,datatype s,datatype t){
if((s>t)||(arr->length==0)){
return false;
}
else {
int k=0;
for(int i=0;ilength;i++){
if((*(arr->fData+i))<=s||*(arr->fData+i)>=t){
*(arr->fData+i-k)=*(arr->fData+i);
}
else {
k++;
}
}
arr->length-=k;
return true;
}
}
5.从顺序表中删除其值在给定值 s 与 t 之间(包含 s 和 t, 要求 s < t ) 的所有元素,如果 s 或 t 不合理或顺序表为空,则显示出错信息并退出运行。
bool deleteST(struct Array *arr,datatype s,datatype t){
if((s>t)||(arr->length==0)){
return false;
}
else {
int k=0;
for(int i=0;ilength;i++){
if((*(arr->fData+i))fData+i)>t){
*(arr->fData+i-k)=*(arr->fData+i);
}
else {
k++;
}
}
arr->length-=k;
return true;
}
}
6.从有序顺序表中删除所有其值重复的元素,使表中所有元素的值均不同
void equal(struct Array *arr){
int k=0;
for(int i=1;ilength;i++){
if(*(arr->fData+k)!=*(arr->fData+i)){
*(arr->fData+k+1)=*(arr->fData+i);
k++;
}
}
arr->length=k+1;
}
7.将两个有序顺序表合并为一个新的有序顺序表,并由函数返回结果顺序表。
假定有序顺序表是递增序列,拿两个指针k,kk分别指向两个序列的值进行比较,将较小的值放入新序列,这样的比较直到其中一个序列结束。将未结束的序列剩下的值合并到新序列。
bool merge(struct Array first,struct Array second,struct Array *result){
if(first.length+second.length>result->max_size){
return false;
}
else {
int k=0,kk=0,kkk=0;
while(kfData+kkk)=*(first.fData+k);
k++;
kkk++;
}
else {
*(result->fData+kkk)=*(second.fData+kk);
kk++;
kkk++;
}
}
if(kfData+kkk)=*(first.fData+i);
kkk++;
}
}
if(kkfData+kkk)=*(second.fData+i);
kkk++;
}
}
result->length=kkk;
return true;
}
}
链表课后题2.3.7:
1.设计一个递归算法,删除不带头结点的单链表 L 中所有值为 x 的结点
void deleteX(nodes **head,datatype x){
if((*head)->next==NULL) return ;
if((*head)->data==x){
nodes *temp;
temp=(*head);
*head=(*head)->next;
free(temp);
deleteX(head,x);
}
else deleteX(&((*head)->next),x);
}
2.在带头结点的单链表 L 中,删除所有值为 x 的结点,并释放其空间,假设值为 x 的结点 不唯一,试编写算法以实现上述操作。
last指向前驱结点。
void deleteII(nodes **head,datatype x){
nodes *temp=(*head)->next;
nodes *last=(*head);
while(temp!=NULL){
if(temp->data==x){
last->next=temp->next;
temp=temp->next;
}
else {
temp=temp->next;
last=last->next;
}
}
}
3. 设 L 为带头结点的单链表,编写算法实现从尾到头反向输出每个结点的值。
递归实现逆置。传入参数是头结点的next指针,以防止将没有数据的头结点也输出出来。
void printII(nodes *head){
if(head==NULL)return ;
printII(head->next);
cout<<"("<data<<")"<
4. 试编写在带头结点的单链表 L 中删除一个最小值结点的高效算法(假设最小值结点是唯 一的)。
用minnum记录当前最小值,用last记录最小值前驱结点,遍历完毕后删除结点。
void deleteMini(nodes **head){
nodes *temp=(*head)->next;
nodes *last=(*head);
nodes *minn;
datatype minnum=999999;
while(temp!=NULL){
if(temp->datadata;
minn=last;
last=last->next;
temp=temp->next;
}
else {
last=last->next;
temp=temp->next;
}
}
minn->next=minn->next->next;
}
5. 试编写算法将带头结点的单链表就地逆直,所谓“就地”是指辅助空间复杂度为 0(1)。
将除头结点外的链拆下来,头插法插回去。
void Reserve(nodes **head){
nodes *first=(*head)->next;
(*head)->next=NULL;
while(first!=NULL){
nodes *temp=first;
first=first->next;
temp->next=(*head)->next;
(*head)->next=temp;
}
}
7.设在一个带表头结点的单链表中所有元素结点的数据值无序,试编写一个函数,删除表 中所有介于给定的两个值(作为函数参数给出)之间的元素的元素(若存在)。
删除值位于[l,r] 。
void deleteLR(nodes **head,datatype l,datatype r){
nodes *first=(*head)->next;
nodes *last=(*head);
while(first!=NULL){
if((first->data)>=l&&(first->data)<=r){
last->next=last->next->next;
first=first->next;
}
else {
last=last->next;
first=first->next;
}
}
}
10.将一个带头结点的单链表 A 分解为两个带头结点的单链表 A 和 B,使得 A 表中含有原表 中序号为奇数的元素,而 B 表中含有原表中序号为偶数的元素, 且保持其相对顺序不变。
返回产生的新链表B的头指针。
nodes * oddOrEven(nodes **headA){
nodes *headB=(nodes*)malloc(sizeof(nodes));
headB->next=NULL;
nodes *tail=headB;//保证顺序尾插
nodes *temp=(*headA)->next;
nodes *last=(*headA);
int ans=1;
while(temp!=NULL){
if(ans%2==0){
tail->next=temp;
tail=temp;
last->next=last->next->next;
temp=temp->next;
tail->next=NULL;
}
else{
last=last->next;
temp=temp->next;
}
ans++;
}
return headB;
}
11. 设 C ={a1, b1, a2, b2·· , an ,bn,,}为线性表,采用带头结点的 he 羊链表存放,设计一个就地 算法,将其拆分为两个线性表,使得 A = {a1,a2,··· , a,,}, B= {bn,,,···,b2, b1}。
返回产生的新链表B的头指针。
nodes * oddOrEvenII(nodes **headA){
nodes *headB=(nodes*)malloc(sizeof(nodes));
headB->next=NULL;//采用头插法
nodes *temp=(*headA)->next;
nodes *last=(*headA);
int ans=1;
while(temp!=NULL){
if(ans%2==0){
nodes *t=temp;
temp=temp->next;
last->next=last->next->next;
t->next=headB->next;
headB->next=t;
}
else {
last=last->next;
temp=temp->next;
}
ans++;
}
return headB;
}
12.在一个递增有序的线性表中,有数值相同的元素存在。 若存储方式为单链表, 设计算法 去掉数值相同的元素, 使表中不再有重复的元素。
void deleteCom(nodes **head){
nodes *temp=(*head)->next;
nodes *last=(*head)->next;
while(temp!=NULL){
while(temp->next!=NULL&&temp->data==temp->next->data){
temp=temp->next;
}
last->next=temp->next;
temp=temp->next;
last=temp;
}
}
13.假设有两个按元素值递增次序排列的线性表, 均以单链表形式存储。 请编写算法将这两 个单链表归并为一个按元素值递减次序排列的单链表,并要求利用原来两个单链表的结 点存放归并后的单链表。
//40.13 假装是有头结点的单链表好了
//双指针指一指,头插回去
//时间复杂度O(m+n)
//空间复杂度O(1)
nodes* mergeI(nodes **headA,nodes **headB){
nodes* tempA=(*headA)->next;
nodes* tempB=(*headB)->next;
(*headA)->next=NULL;
while(tempA!=NULL&&tempB!=NULL){
if(tempB->datadata){
nodes *t=tempB;
tempB=tempB->next;
t->next=(*headA)->next;
(*headA)->next=t;
}
else {
nodes *t=tempA;
tempA=tempA->next;
t->next=(*headA)->next;
(*headA)->next=t;
}
}
while(tempA!=NULL){
nodes *t=tempA;
tempA=tempA->next;
t->next=(*headA)->next;
(*headA)->next=t;
}
while(tempB!=NULL){
nodes *t=tempB;
tempB=tempB->next;
t->next=(*headA)->next;
(*headA)->next=t;
}
return (*headA);
}
14. 设 A 和 B 是两个单链表 (带头结点 ), 其中元素递增有序。 设计一个算法从 A 和 B 中的 公共元素产生单链表 C,要求不破坏 A、 B 的结点。
//40.14 双指针比一比
nodes *getCommon(nodes *headA,nodes *headB){
nodes* tempA=headA->next;
nodes* tempB=headB->next;
nodes* headC=(nodes*)malloc(sizeof(nodes));
headC->next=NULL;
nodes* tail=headC;
while(tempA!=NULL&&tempB!=NULL){
if(tempA->datadata){
tempA=tempA->next;
}
else if(tempA->data>tempB->data){
tempB=tempB->next;
}
else if(tempA->data==tempB->data){
nodes* temp=(nodes*)malloc(sizeof(nodes));
temp->data=tempA->data;
tail->next=temp;
tail=temp;
tail->next=NULL;
tempA=tempA->next;
tempB=tempB->next;
}
}
return headC;
}
15. 已知两个链表 A 和 B 分别表示两个集合,其元素递增排列。 编制函数,求 A 与 B 的交 集,并存放于 A 链表中 。
//40.15 得到两递增链表交集
//最后将结果放入A中,并释放剩余结点
void getIntersection(nodes **headA,nodes **headB){
nodes *tempA=(*headA)->next;
nodes *tempB=(*headB)->next;
nodes *tempC=(*headA);//将已经遍历过的结点改成交点
while(tempA!=NULL&&tempB!=NULL){
if(tempA->datadata){
tempA=tempA->next;
}
else if(tempA->data>tempB->data){
tempB=tempB->next;
}
else {
tempC=tempC->next;
tempC->data=tempA->data;
if(tempA->next!=NULL&&tempA->data!=tempA->next->data){
tempA=tempA->next;
}
if(tempB->next!=NULL&&tempB->data!=tempB->next->data){
tempB=tempB->next;
}
//防止交集出现重复
while(tempA->next!=NULL&&tempA->data==tempA->next->data){
tempA=tempA->next;
}
while(tempB->next!=NULL&&tempB->data==tempB->next->data){
tempB=tempB->next;
}
}
}
nodes *f=tempC->next;
tempC->next=NULL;
while(f!=NULL){
nodes* ff=f;
f=f->next;
free(ff);
}
}
16.两个整数序列 A =a1,a2,a3···, am 和 B=b1,b2, b3,…, bn 已经存入两个单链表中,设计一 个算法,判断序列 B 是否是序列 A 的连续子序列 。
//40.16 true是子序列
bool cmp(nodes *headA,nodes *headB){
nodes *tempA=headA->next;
nodes *tempB=headB->next;
while(tempA!=NULL&&tempB!=NULL){
if(tempB->data==tempA->data){
tempB=tempB->next;
tempA=tempA->next;
}
else if(tempB->data!=tempA->data){
tempA=tempA->next;
}
}
if(tempA==NULL){
return false;
}
if(tempB==NULL){
return true;
}
}
21.一个带头结点的单链表,找到倒数第k个结点,输出这个结点的数据,查找成功,函数返回1,否则返回0。
//40.21 两个错位指针
int getK(nodes *head,int k){
nodes *tempA=head->next;
nodes *tempB=head->next;
int ans=1;
while(tempA!=NULL&&ans<=k){
tempA=tempA->next;
ans++;
}
if(tempA==NULL){
return 0;
}
while(tempA!=NULL){
tempB=tempB->next;
tempA=tempA->next;
}
cout<data<
栈课后题3.1.5
3.(2),写出一个算法,判定所给的操作序列是否合法。若合法,返回 true, 否则返回 false (假定被判定的操作序列已存入一维数组中)。
判断标准:
遍历一遍,每遍历到字符O时,O的个数不能大于I的个数,否则不合法。遍历到最后,I的个数应该等于O的个数,否则不合法。
bool isLegal(char str[]){
int l=strlen(str);
int numI=0;
int numO=0;
for(int i=0;inumI){
return false;
}
}
if(str[i]=='I'){
numI++;
}
}
if(numI!=numO)return false;
return true;
}
4.设单链表的表头指针为 L,结点结构由 data 和 next 两个域构成,其中 data 域为字 符型。 试设计算法判断该链表的全部 n 个字符是否中心对称。 例如 xyx、 xyyx 都是中 心对称。
将字符串的一半压入栈中,将栈顶与字符串剩下一半逐个对比。
链表和链栈用到的结点
typedef int datatype;
struct nodes{
datatype data;
nodes *next;
};
用到的栈:
//带头结点的链栈
struct linkStack{
nodes *head;//头指针
//初始化
void init(){
head=(nodes*)malloc(sizeof(nodes));
head->next=NULL;
}
//判空
bool isEmpty(){
if(head->next==NULL){
return true;
}
else return false;
}
//进栈
void pushStack(datatype newOne){
nodes *temp=(nodes*)malloc(sizeof(nodes));
temp->data=newOne;
temp->next=head->next;
head->next=temp;
}
//出栈
bool popStack(){
if(isEmpty()){
return false;
}
else {
nodes *temp=head->next;
head->next=head->next->next;
free(temp);
return true;
}
}
//得到栈顶元素
datatype getTop(){
if(!isEmpty()){
return head->next->data;
}
}
void freeStack(){
nodes *temp=head;
while(temp!=NULL){
nodes *t=temp;
temp=temp->next;
free(t);
}
}
};
用到的链表
//带头结点的链表
struct myList{
nodes *head;
void init(){
head=(nodes*)malloc(sizeof(nodes));
head->next=NULL;
}
//头插法
void insertList(datatype newOne){
nodes *temp=(nodes*)malloc(sizeof(nodes));
temp->data=newOne;
temp->next=head->next;
head->next=temp;
}
void printList(){
nodes *temp=head->next;
while(temp!=NULL){
cout<data<<"----";
temp=temp->next;
}
cout<
判断是否对称的函数
bool isSymmetry(myList li){
linkStack st;
st.init();
int len=0;
nodes *temp=li.head->next;
while(temp!=NULL){
len++;
temp=temp->next;
}
temp=li.head->next;
for(int i=1;i<=len/2;i++){
st.pushStack(temp->data);
temp=temp->next;
}
if(len%2==1)temp=temp->next;
for(int i=1;i<=len/2;i++){
if(st.getTop()!=temp->data){
return false;
}
st.popStack();
temp=temp->next;
}
st.freeStack();
return true;
}
5.设有两个栈s1 、 s2 都采用顺序栈方式,并共享一个存储区[ 0, ., maxsize-1 ],为了 尽量利用空间,减少溢出的可能,可采用栈顶相向、迎面增长的存储方式。 试设计 s1 、 s2 有关入栈和出栈的操作算法。
见这篇
https://blog.csdn.net/killers_999/article/details/107900446