數據結構之線性表:單鏈表(王道2021習題算法實現及測試)

#include <iostream>
#include<algorithm>
#include<cstdio>
using namespace std;

typedef int ElemType;
typedef struct LNode{
    ElemType data;
    struct LNode *next;
}LNode, *LinkList;

//函數聲明
LNode *List_TailerInsert(LNode *&L);
int ListLength(LNode *L);
void Print_LinkList(LNode *L);

//尾插法,以-1結束輸入。
LNode *List_TailerInsert(LNode *&L){
    L = (LNode*)malloc(sizeof(LNode));
    int x = 0;
    LNode *s, *r = L;
    L->next = NULL;
    scanf("%d", &x);
    while(x!=-1){
        s = (LNode*)malloc(sizeof(LNode));
        s->data = x;
        r->next = s;
        r = s;
        scanf("%d", &x);
    }
    r->next = NULL;
    return L;
}

//求表長
int ListLength(LNode *L){
    int len = 0;
    LNode *p = L->next;
    while(p){
        len++;
        p = p->next;
    }
    return len;
}
//順序輸出
void Print_LinkList(LNode *L){
    LNode *p = L->next;
    while(p!=NULL){
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}

///*******************課後習題********************///
//2、刪除所有值爲x的結點並釋放其空間
LNode *DeleteX(LNode *&L, int x){
    LNode *p = L;
    while(p->next){
        LNode *q = p->next;
        if(q->data == x){
            p->next = q->next;
            free(q);
        }
        p = p->next;
    }
    return L;
}

//3、反向輸出單鏈表中元素
void PrintReserve(LNode *L){
    if(L->next!=NULL) PrintReserve(L->next);
    printf("%d ", L->data);
}

//4、刪除最小值元素
LNode *DeleteMIN(LNode *&L){
    LNode *pre = L, *MinPre = L->next;
    ElemType Min = 2147483647;
    while(pre->next){
        LNode *p = pre->next;
        if(p->data<Min){
            MinPre = pre;
            Min = p->data;
        }
        pre = pre->next;
    }
    LNode *q = MinPre->next;
    MinPre->next = q->next;
    free(q);
    return L;
}

//5、就地逆置單鏈表
LNode *Reserve(LNode *&L){
    LNode *p = L->next;
    if(p==NULL) return L;
    LNode *q = p->next;
    if(q==NULL) return L;
    LNode *r = q->next;
    while(true){
        if(r==NULL){
            q->next = p;
            L->next->next = NULL;
            L->next = q;
            break;
        }
        q->next = p;
        p = q;
        q = r;
        r = r->next;
    }
    return L;
}
//6、給單鏈表中元素排序
LNode *Sort(LNode *&L){
    LNode *p = L->next;
    int i = 0, k = 0;
    ElemType a[1005];
    while(p){
        a[k++] = p->data;
        p = p->next;
    }
    sort(a, a+k);
    printf("%d\n", a[0]);
    p = L->next;
    while(k--){
        p->data = a[i++];
        p = p->next;
    }
    return L;
}

//7、刪除單鏈表中在l和r之間的元素
LNode *DeleteLR(LNode *&L, ElemType l, ElemType r){
    LNode *p = L, *q;
    while(p->next){
        q = p->next;
        if(q->data>l && q->data<r){
            p->next = q->next;
            free(q);
        }
        else p = p->next;
    }
    return L;
}

//8、給定兩個單鏈表,找出它們的公共結點
LNode *Search_list_common(LNode *L1, LNode *L2){
    int len1 = ListLength(L1), len2 = ListLength(L2);
    LNode *longlist, *shortlist;
    if(len1>len2){
        longlist = L1;
        shortlist = L2;
    }
    else{
        longlist = L2;
        shortlist = L1;
    }
    int dist = abs(len1 - len2);
    while(dist--) longlist = longlist->next;
    while(longlist){
        if(longlist==shortlist)
            return longlist;
        else{
            longlist = longlist->next;
            shortlist = shortlist->next;
        }
    }
    return NULL;
}

//9、設計原地算法,按遞增順序輸出單鏈表中元素並釋放其空間
void MinDelete(LNode *&L){
    while(L->next){
        LNode *pre = L, *p = L->next, *MinPre = pre, *Min = p;
        while(p){
            if(p->data<Min->data){
                Min = p;
                MinPre = pre;
            }
            else{
                pre = p;
                p = p->next;
            }
        }
        MinPre->next = Min->next;
        printf("%d ", Min->data);
        free(Min);
    }
    printf("\n");
}

//10、將單鏈表A拆成A,B,分別存放奇數位和偶數位的元素
LNode *disCreat_1(LNode *&A){
    LNode *B = (LNode*)malloc(sizeof(LNode));
    B->next = NULL;
    LNode *PAPre = A, *PA = A->next, *PB = B;
    int k = 0;
    while(PA){
        k++;
        if(k%2) {
            PAPre = PA;
            PA = PA->next;
        }
        else{
            LNode *s = PA;
            //deal with A
            PAPre->next = PA->next;
            PA = PA->next;
            //deal with B
            PB->next = s;
            s->next = NULL;
            PB = s;
        }
    }
    return B;
}

//11、設計就地算法,將單鏈表A={a1,b1,a2,b2....an,bn}拆成兩個單鏈表A={a1,a2...an},B={bn....b2,b1}
LNode *disCreat_2(LNode *&A){
    LNode *B = (LNode*)malloc(sizeof(LNode));
    B->next = NULL;
    LNode *PAPre = A, *PA = A->next;
    int k = 0;
    while(PA){
        k++;
        if(k%2) {
            PAPre = PA;
            PA = PA->next;
        }
        else{
            LNode *s = PA;
            //deal with A
            PAPre->next = PA->next;
            PA = PA->next;
            //deal with B
            s->next = B->next;
            B->next = s;
        }
    }
    return B;
}

//12、遞增有序單鏈表中有充重複元素存在,將頻數大於1的元素刪除只留一個。
//(3 4 5 5 6 6 6 7 2 -1)->(3 4 5 6 7 2 -1)
LNode *DeleteSame(LNode *&L){
    if(ListLength(L)<2) return L;
    LNode *pre = L->next, *p = pre->next;
    while(p){
        if(pre->data==p->data){
            LNode *q = p;
            pre->next = q->next;
            p = q->next;
            free(q);
        }
        else{
            pre = p;
            p = p->next;
        }
    }
    return L;
}

//13、設計原地算法。將兩個遞增的單鏈表A,B合併成一個遞減的單鏈表L
LNode *MergeList(LNode *&A, LNode *&B){
    LNode *L = (LNode*)malloc(sizeof(LNode));
    L->next = NULL;
    LNode *PA = A->next, *PB = B->next, *s;//s用於臨時保存指針
    while(PA && PB){
        if(PA->data < PB->data){
            s = PA;
            A->next = PA->next;
            PA = s->next;
        }
        else{
            s = PB;
            B->next = PB->next;
            PB = s->next;
        }
        //insert to L
        s->next = L->next;
        L->next = s;
    }
    if(PA) PB = PA;
    while(PB){
        s = PB;
        B->next = PB->next;
        PB = s->next;
        s->next = L->next;
        L->next = s;
    }
    return L;
}

///*******************課後習題********************///

int main(){
    LNode *L, *L1, *AB;
    List_TailerInsert(L);
    List_TailerInsert(L1);
    AB = MergeList(L, L1);
    Print_LinkList(AB);
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章