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;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 

 

 

 

 


 


 

 

 

 

 

 

 

 


 

 

你可能感兴趣的:(Data,Structure,数据结构,c++)