PTA數據結構與算法題目集(中文) 函數題(2)

4-6 帶頭結點的鏈式表操作集

code:

List MakeEmpty()
{
    List L;
    L = (List)malloc(sizeof(struct LNode));
    L->Data = NULL;
    L->Next = NULL;
    return L;
}
Position Find( List L, ElementType X )
{
    List p = L;
    while(p && p->Data!=X) {
        p = p->Next;
    }
    if(p && X==p->Data) {
        return p;
    } else {
        return ERROR;
    }
}
bool Insert( List L, ElementType X, Position P )
{
    List r = L;
    List pre = L;
    while(r && P!=r) {
        pre = r;
        r = r->Next;
    }
    if(r==P) {
        List p = (List)malloc(sizeof(struct LNode));
        p->Data = X;
        p->Next = r;
        pre->Next = p;
        return true;
    }
    printf("Wrong Position for Insertion\n");
    return false;
}
bool Delete( List L, Position P )
{

    List r = L;
    List pre = L;
    while(r && r!=P)
    {
        pre = r;
        r = r->Next;
    }
    if(r==P) {
        pre->Next = P->Next;
        free(P);
        List k = pre->Next;
        return true;
    }
    printf("Wrong Position for Deletion\n");
    return false;
}

P.S:這道題需要寫四個函數,分別是鏈表的置空,查詢某個元素,還有元素的插入和刪除,都是一些鏈表的基本操作,題中的鏈表是有頭節點的,而開始的題中的鏈表是沒有使用頭節點的,這個與前面的有一些區別,其實擁有頭節點的鏈表更容易操作,在插入時不用考慮是否是第一個結點了,更加好寫些,同樣要注意Find函數,它需要返回的是這個元素的Position,而它是一個指針變量,而不是代表其位置的整型變量。

4-7 在一個數組中實現兩個堆棧

P.S:很頭疼,這一題沒有通過,報的錯誤也是十分無奈,超時,所以也不知道怎樣去解決這個問題,如何去優化代碼,這道題其實是一個數組嘛,兩個棧的棧底在兩頭,設計應該就是這樣,但是給我報超時錯誤,暫時先放下吧,以後通過再補上來。

更新:補上成功的code,今天突然再次提交,居然就通過了,看來我的想法是沒有問題的^_^

code:

Stack CreateStack( int MaxSize )
{
    Stack S = (Stack)malloc(sizeof(struct SNode));
    S->MaxSize = MaxSize;
    S->Data = (ElementType *)malloc(sizeof(ElementType)*MaxSize);
    S->Top2 = MaxSize;
    S->Top1 = -1;
    return S;
}
bool Push(Stack S, ElementType X, int Tag){
    if(S->Top1+1 == S->Top2){
        printf("Stack Full\n");
        return false;
    }else{
        if(Tag == 1){
            S->Top1++;
            S->Data[S->Top1] = X;
        }else{
            S->Top2--;
            S->Data[S->Top2] = X;
        }
    }
    return true;
}

ElementType Pop(Stack S, int Tag){
    int X;
    if(Tag == 1){
        if(S->Top1 == -1){
            printf("Stack 1 Empty\n");
            return ERROR;
        }else{
            X = S->Data[S->Top1];
            S->Top1--;
            return X;
        }
    }else if(Tag == 2){
        if(S->Top2 == S->MaxSize){
            printf("Stack 2 Empty\n");
            return ERROR;
        }else{
            X = S->Data[S->Top2];
            S->Top2++;
            return X;
        }
    }
}

4-8 求二叉樹高度

code:

int GetHeight( BinTree BT )
{
    if (BT == NULL)  
        return 0;  
    else {  
        int left = GetHeight(BT->Left);
        int right = GetHeight(BT->Right);
        if(left>=right)
            return 1 + left;
        else 
            return 1 + right;
    }  
}

P.S:求一顆二叉樹的高度,我直接使用了遞歸實現,所以也十分的清晰易懂。

4-9 二叉樹遍歷

這道題吧,也木有通過,其實是不願寫吧,前序,中序,後續遍歷都很簡單,但是層序便利時,我們知道需要藉助隊列來實現,而在函數題中又不能用那種頭文件,因此我想了想,但後來腦子就不舒服,先放下,後面補上。

更新:今天想了想,其實沒有必要用隊列的,可以簡單點嘛,開始怎麼就那麼蠢呢,隊列也是由數組或鏈表構成的,而這道題又不需要考慮隊列滿或者空的情況,自己用一個數組代替不就是了,其實很簡單的啦,我才用了一個容量爲100的數組來模擬隊列,最後就這樣成功啦,前中後三種遍歷就沒有什麼好說的咯,遞歸,簡單易懂,用棧的話也不難,但是能簡單就簡單嘛

code:

void InorderTraversal( BinTree BT ){
    if(BT){
        InorderTraversal(BT->Left);
        printf(" %c", BT->Data);
        InorderTraversal(BT->Right);
    }
}

void PreorderTraversal( BinTree BT ){
    if(BT){
        printf(" %c",BT->Data);
        PreorderTraversal(BT->Left);
        PreorderTraversal(BT->Right);
    }
}

void PostorderTraversal( BinTree BT )
{
    if(BT != NULL){
        PostorderTraversal(BT->Left);
        PostorderTraversal(BT->Right);
        printf(" %c", BT->Data);
    }
}

void LevelorderTraversal( BinTree BT ) {
    BinTree str[100];
    int rear = -1, front = -1;
    BinTree T;

    if(!BT)
        return;
    rear = rear+1;
    str[rear] = BT;
    while(rear != front){
        front = front+1;
        T = str[front];
        printf(" %c", T->Data);
        if(T->Left) {
            rear = rear+1;
            str[rear] = T->Left;
        }
        if(T->Right){
            rear++ ;
            str[rear] = T->Right;
        }
    }
}

4-10 二分查找

code:

Position BinarySearch( List Tbl, ElementType K )
{
    int left, right, middle;
    left = 1, right = Tbl->Last;
    while (left <= right)
    {
        middle = (left + right) / 2;
        if (Tbl->Data[middle] > K)
        {
            right = middle - 1;
        }
        else if (Tbl->Data[middle] < K)
        {
            left = middle + 1;
        }
        else if(Tbl->Data[middle] == K)
        {
            return middle;
        }
    }
    return NotFound;
}

P.S:二分查找算法,也叫折半查找,也就是將數組每次只查找一半,因此可以省去很多的比較次數,也就提高了效率,減少了查找時間,是一個很好,很基礎的算法
*

4-11 先序輸出葉結點

code:

void PreorderPrintLeaves( BinTree BT ){
    if(BT != NULL){
        PreorderPrintLeaves(BT->Left);
        if(BT->Data >='A' && BT->Data <='z' && BT->Left == NULL && BT->Right == NULL){
            printf(" %c",BT->Data);
        }
        PreorderPrintLeaves(BT->Right);
    }
}

P.S:先序輸出葉子結點,說白了就是先序遍歷唄,不過在先序遍歷的基礎上進行一下判斷,當左右子節點都爲空時才輸出來。

4-12 二叉搜索樹的操作集

P.S:這道題部分正確,可能是沒有考慮全面,前三個測試點不能通過,後兩個可以,所以等通過之後再放上代碼。

更新:調了很多次,這道雖然是教材上的,但是刪除操作是真的很複雜,需要很細心頭腦很清晰的去寫,下面的是code,參考了教材上的源碼,最後居然讓我發現了一個小錯誤,教材上查找最大最小元素函數的判斷語句中多了個“!”,很容易就發現啦,但是不一定會注意到,慢慢寫啦!!

code:

BinTree Insert( BinTree BST, ElementType X )
{
    if(!BST) {          /* 若原樹爲空,生成並返回一個結點的二叉搜索樹 */
        BST = (BinTree)malloc(sizeof(struct TNode));
        BST ->Data = X;
        BST ->Left = BST ->Right = NULL;
    }else {         /* 開始尋找要插入元素的位置 */
        if(X < BST ->Data ) {
            BST ->Left = Insert(BST ->Left, X);
        }else if(X > BST ->Data ) {
            BST ->Right = Insert(BST ->Right, X);
        }
        /* X已經存在,不用操作 */
    }
    return BST;
}
BinTree Delete( BinTree BST, ElementType X )
{
    Position Tmp;
    if(!BST) {
        printf("Not Found\n");
    }else {
        if( X < BST->Data) {
            BST ->Left = Delete(BST->Left, X);  /* 左子樹遞歸刪除 */
        }else if(X > BST->Data ) {
            BST ->Right = Delete(BST->Right , X);    /* 右子樹遞歸刪除*/
        }else {     /* 找到需要刪除的結點 */
            if(BST->Left && BST->Right) {
                /* 被刪除的結點有左右子結點 */
                Tmp = FindMin( BST ->Right);   /* 在右子樹中找到最小結點填充刪除結點 */
                BST ->Data = Tmp ->Data;
                BST ->Right = Delete(BST ->Right, BST ->Data);  /* 在刪除結點的右結點中刪除最小元素 */
            }else {     /* 被刪除結點有一個或沒有子結點*/
                Tmp = BST;
                if(!BST ->Left) {   /*有右孩子或無子結點*/
                    BST = BST->Right;
                }else if(!BST->Right) {  /* 有左孩子或無子節點*/
                    BST = BST->Left;
                }
                free(Tmp);
            }
        }
    }
    return BST;
}
Position Find( BinTree BST, ElementType X )
{
    if(!BST) {
        return NULL;    // 查找失敗
    }
    if(X > BST->Data) {
        return Find(BST->Right, X);     //在右子樹中繼續查找
    }else if(X < BST->Data) {
        return Find(BST->Left, X);      //在左子樹中繼續查找
    }else {
        return BST;                     //查找成功
    }
}
Position FindMin( BinTree BST )
{
    if(BST) {
        while(BST->Left) {
            BST = BST->Left;        //沿着左分支一直查找,直到葉子結點
        }
    }
    return BST;
}
Position FindMax( BinTree BST )
{
    if(BST) {
        while(BST->Right) {
            BST = BST->Right;        //沿着右分支一直查找,直到葉子結點
        }
    }
    return BST;
}

函數題就這12道,其中已經完全通過了9道,還有3道暫時沒有通過,要不超時,要不部分正確,暫時想也想不出來,想的也比較難過,所以等什麼時候有空無聊時再想想,然後通過了再補上吧,如果能給予想法的話請聯繫我呀,一起交流,一起分享,一起進步^_^

今天將原先沒放上的都解決啦,12道函數題完成,雖然都是很基礎的數據結構,但是真要全部靠自己寫出來很困難困難,多多練習咯,後面就慢慢刷編程題咯,刷題的快感~~~

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