2021年王道数据结构课后题

顺序表课后题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;i<arr->length;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;i<arr->length/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;i<arr->length;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;i<arr->length;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;i<arr->length;i++){
            if((*(arr->fData+i))<s||*(arr->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;i<arr->length;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(k<first.length&&kk<second.length){
            if(*(first.fData+k)<=*(second.fData+kk)){
                *(result->fData+kkk)=*(first.fData+k);
                k++;
                kkk++;
            }
            else {
                *(result->fData+kkk)=*(second.fData+kk);
                kk++;
                kkk++;
            }
        }
        if(k<first.length){
            for(int i=k;i<first.length;i++){
                *(result->fData+kkk)=*(first.fData+i);
                kkk++;
            }
        }
        if(kk<second.length){
            for(int i=kk;i<second.length;i++){
                *(result->fData+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<<"("<<head->data<<")"<<endl;
}

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->data<minnum){
            minnum=temp->data;
            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->data<tempA->data){
            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->data<tempB->data){
            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->data<tempB->data){
            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<<tempB->data<<endl;
    return 1;
}

栈课后题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;i<l;i++){
        if(str[i]=='O'){
            numO++;
            if(numO>numI){
                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<<temp->data<<"----";
            temp=temp->next;
        }
        cout<<endl;
    }
};

判断是否对称的函数 

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 

 

 

 

 


 


 

 

 

 

 

 

 

 


 

 

  • 5
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
王道数据结构课后中,有一个关于排序的目。根据引用的思路,我们可以使用排序后查找的方法来解决这个问。具体步骤如下: 1. 首先,对给定的数据进行排序,可以使用快速排序、归并排序等常见的排序算法进行排序。排序的时间复杂度为O(log2n)。 2. 排序完成后,我们可以使用二分查找的方法来查找特定元素。如果目标元素存在于排序后的数组中,可以通过遍历判断其是否存在。时间复杂度为O(log2n)。 所以,根据引用的思路,我们可以使用排序后查找的方法来解决王道数据结构课后中排序的问。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [leetcode答案-kaoyan-data-structure:21考研,用的去的书《2020王道数据结构》](https://download.csdn.net/download/weixin_38733733/19920375)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [王道数据结构课后编程(顺序表)](https://blog.csdn.net/RHJlife/article/details/90450834)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值