逆置单链表(基于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,看图请注意!!!)


浙公网安备 33010602011771号