逆置单链表(基于c语言)

直接插入全部代码:(reverseLinklist函数是逆置操作)

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

typedef int LDataType;
typedef struct Linklist{
    LDataType data;
    struct Linklist *next;
}Linklist,*pLinklist;

pLinklist BuyNewNode(LDataType data);    //动态生成新结点
void InitLinklist(pLinklist *pL);    //初始化单链表
void PushBackLinklist(pLinklist *pL,LDataType data);    //尾插
void PushFrontLinklist(pLinklist *pL,LDataType data);    //头插
void PopBackLinklist(pLinklist* pL);    //尾删
void PopFrontLinklist(pLinklist *pL);    //头删 
void PrintLinklist(Linklist *pL);    //打印单链表
pLinklist FindLinklist(pLinklist *pL,LDataType data);    //查找指定元素,返回元素位置
void InsertLinklist(pLinklist *pL,pLinklist p,LDataType data);    //指定位置插入
void RemoveLinklist(pLinklist* pL,LDataType data);    //删除第一个指定元素
void RemoveAllLinklist(pLinklist *pL,LDataType data);    //删除所有指定元素
int IsEmptyLinklist(pLinklist pL);    //判断链表是否为空
void DestoryLinklist(pLinklist *pL);    //销毁单链表
pLinklist reverseLinklist(pLinklist *pL); 

int main(void){
    Linklist *first = NULL;
    InitLinklist(&first);
    PushBackLinklist(&first,5);
    PushBackLinklist(&first,4);
    PushBackLinklist(&first,3);
    PushBackLinklist(&first,2);
    PushBackLinklist(&first,1);
    PushBackLinklist(&first,0);
    PushFrontLinklist(&first,6);
    first = reverseLinklist(&first);
    PushFrontLinklist(&first,-1);
    PrintLinklist(first);
}



pLinklist BuyNewNode(LDataType data){
    pLinklist NewNode = (pLinklist)malloc(sizeof(Linklist));
    if (NewNode == NULL){
        printf("动态开辟内存空间失败\n");
        return NULL;
    }
    NewNode->data = data;
    NewNode->next = NULL;
    return NewNode;
} 
void InitLinklist(pLinklist *pL){
    assert(pL != NULL);    //初始化操作 
    (*pL) = NULL;
}
void PushBackLinklist(pLinklist *pL,LDataType data){
    assert(pL != NULL);    //尾插一个数据域为data的结点 
    pLinklist NewNode = BuyNewNode(data);
    if(*pL == NULL){
        *pL = NewNode;
        return ;
    }
    pLinklist cur = *pL;
    while(cur->next){
        cur = cur->next;
    }
    cur->next = NewNode;
}
void PushFrontLinklist(pLinklist *pL,LDataType data){
    assert(pL != NULL);    //头插一个数据域为data的结点 
    pLinklist NewNode = BuyNewNode(data);
    if(*pL == NULL){
        *pL = NewNode;
        return ;
    }
    NewNode->next = *pL;
    *pL = NewNode;
}
int IsEmptyLinklist(pLinklist pL){
    return (pL == NULL);    //判断无头单链表是否为空 
}
void PopBackLinklist(pLinklist *pL){
    assert(pL != NULL);    //尾删 
    if(IsEmptyLinklist(*pL)){
        puts("链表为空,删除失败");
        return ;
    }
    pLinklist cur = *pL;
    pLinklist pre;
    if(cur->next == NULL){
        //只有一个结点
        *pL = NULL;
        free(cur);
        cur = NULL;
        return ; 
    }
    while(cur->next){
        pre = cur;
        cur = cur->next;
    }
    pre->next = NULL;
    free(cur);
    cur = NULL;
}
void PopFrontLinklist(pLinklist *pL){
    assert(pL != NULL);    //头删,既是删除第一个结点 
    if(*pL == NULL){
        printf(" 链表为空,删除失败");
        return ;
    }
    pLinklist cur = *pL;
    *pL = cur->next;
    free(cur);
    cur = NULL;
}
pLinklist FindLinklist(pLinklist *pL,LDataType data){
    assert( pL != NULL);    //找到第一个数据为data的结点 
    pLinklist cur = *pL;
    while(cur){
        if (cur->data == data){
            return cur;
        }
        cur = cur->next;
    }
    return NULL;
}
void InsertLinklist(pLinklist *pL,pLinklist p,LDataType data){
    assert(pL != NULL);    //xiangp结点之前插入一个数据为data的元素 
    pLinklist NewNode = BuyNewNode(data);
    pLinklist cur = *pL;
    while(cur->next != p){
        cur = cur->next;
    }
    NewNode->next = p;
    cur->next = NewNode;
}
void RemoveLinklist(pLinklist *pL,LDataType data){
    assert(pL != NULL);    //删除第一个数据域为data的结点 
    pLinklist cur = NULL;
    pLinklist p = *pL;
    pLinklist pre = NULL;
    cur = FindLinklist(pL,data);
    if (cur == NULL){
        printf("未找到要删除的元素");
        return ;
    }
    if (*pL == cur){
        //位于第一个结点
        *pL = cur->next;
        free(cur);
        cur = NULL;
        return ; 
    }
    while(p != cur){
        pre = p;
        p = p->next;
    }
    pre->next = cur->next;
    free(cur);
    cur = NULL;
}
void RemoveAllLinklist(pLinklist *pL,LDataType data){
    assert(pL != NULL);    //删除每一个数据域都是data的结点 
    pLinklist cur = NULL;
    pLinklist p = *pL;
    pLinklist pre = *pL;
    while(p){
        if (p->data == data && (*pL) == p){
            //第一个结点是 
            pre = p;
            p = p->next;
            *pL = p;
            free(pre);
            pre = NULL;
        }
        else if(p->data == data){
            //后续结点是 
            cur = p;
            p = p->next;
            pre->next = p;
            free(cur);
            cur = NULL;
        }
        else{
            //此结点不是 
            pre = p;
            p = p->next;
        }
    }
}
void PrintLinklist(Linklist *pL){
    pLinklist cur = pL;    //打印链表 
    while(cur){
        printf("%d--->",cur->data);
        cur = cur->next;
    }
    printf("NULL\n");
} 
void DestoryLinklist(pLinklist *pL){
    assert(pL != NULL);    //摧毁链表 
    pLinklist cur = *pL;
    pLinklist pre = NULL;
    if (*pL == NULL){
        printf("链表为空");
        return ;
    }
    if (cur->next = NULL){
        *pL = NULL;
        free(cur);
        cur = NULL;
        return ;
    }
    while(cur){
        pre = cur;
        cur = cur->next;
        free(pre);
        pre = NULL;
    }
}
pLinklist reverseLinklist(pLinklist *pL){
    if((*pL) == NULL || pL == NULL){
        return NULL;
    }
    if((*pL)->next == NULL){
        return *pL;
    }
    Linklist *p = *pL;
    Linklist *q = (*pL)->next;
    Linklist *r = *pL;
    while(q->next != NULL){
        r = q->next;
        q->next = p;
        p = q;
        q = r;
        r = r->next;
    }
    q->next = p;
    (*pL)->next = NULL;
    *pL = q;
    return *pL;
}

 第一步就是判断这个单链表是否为空,因为我用了二级指针,因此要看链表为空的同时还要看pL是否指向有问题。

然后看几个元素,如果只有一个元素的话,直接返回就行了,剩下的难点是如何解决超过一个元素的链表;

注意到我用了p,q,r;三个指向结点的指针,p是存前一个元素,q是实现逆置的指针,通过它来指向前面那一个结点,r是后面的指针,其存在的意义是为了让q有后续,因为q指向其他地方后,无法通过p = p->next进行传递。下面是图示。

 

 

 我感觉应该听得懂。(图中最后一步没有在图中把原来头指针指向结点的next域改为NULL,看图请注意!!!

 

posted @ 2021-03-26 19:13  吃心王  阅读(547)  评论(0)    收藏  举报