【C语言】单链表

来源:互联网 发布:好女人是什么样的 知乎 编辑:程序博客网 时间:2024/05/18 08:55

    程序实现了单链表的基本操作,包括创建,初始化,销毁,头插,头删,尾插,尾删,打印单链表,查找指定数据的位置,指定位置插入指定数据,删除指定数据,删除链表里出现的所有指定数据,指定位置删除,单链表的冒泡排序。博主现阶段还是技术小白,此初步调试完成,读者如果发现新的bug,还请不吝赐教!

    先介绍一下单链表的概念:

单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。

    链表中的数据是以结点来表示的,每个结点的构成:元素( 数据) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元指针就是连接每个结点的地址数据。

以“结点的序列”表示线性表称作 线性链表(单链表)

单链表是链式存取的结构,为找第 i 个 数据元素,必须先找到第 i-1 个数据元素。而且单链表只能从前往后遍历。

接下来分享一下我的实现:

头文件部分:

#define _CRT_SECURE_NO_WARNINGS 1#ifndef _LINKLIST_H__#define _LINKLIST_H__#include<stdio.h>#include<stdlib.h>#include<assert.h>typedef int DataType;typedef struct LinkNode{DataType data;struct LinkNode *next;}LinkNode,*pLinkNode;typedef struct LinkList{LinkNode *pHead;}LinkList,*pLinkList;void InitLinkList(pLinkList pList);  //初始化单链表void DestroyList(pLinkList pList);   //销毁单链表void PushBack(pLinkList pList, DataType x);  //尾插void PopBack(pLinkList pList);        //尾删void PushFront(pLinkList pList, DataType x);   //头插void PopFront(pLinkList pList);          //头删void PrintList(pLinkList pList);         //打印单链表pLinkNode Find(pLinkList pList, DataType x);   //查找指定元素的地址void Insert(pLinkList pList, pLinkNode pos, DataType x);// 指定位置插入指定数据void Remove(pLinkList pList, DataType x);//删除指定数据void RemoveAll(pLinkList pList, DataType x);//删除链表里出现的所有指定数据void Erase(pLinkList pList, pLinkNode pos);  //指定位置删除void BubbleSort(pLinkList pList);   //单链表的冒泡排序#endif //_LINKLIST_H__
函数实现:

#include"linklist.h"void InitLinkList(pLinkList pList){assert(pList);pList->pHead = NULL;}void DestroyList(pLinkList pList){assert(pList);pLinkNode cur;cur = pList->pHead;while (cur){pLinkNode del = cur;cur = cur->next;free(del);del = NULL;}pList->pHead = NULL;}pLinkNode BuyNewNode(DataType x)   //创建一个新结点并返回{pLinkNode NewNode = NULL;NewNode = (pLinkNode)malloc(sizeof(LinkNode));if (NewNode == NULL){printf("out of memory\n");exit(EXIT_FAILURE);}NewNode->data = x;NewNode->next = NULL;return NewNode;}void PushBack(pLinkList pList, DataType x){assert(pList);pLinkNode cur=NULL;pLinkNode NewNode=BuyNewNode(x);cur = pList->pHead;if (cur == NULL)   //若为空链表直接将新结点设置为头结点{pList->pHead = NewNode;}else{while ((cur->next) != NULL)    //找到链表的最后一个位置{cur = cur->next;}cur->next = NewNode;}}void PopBack(pLinkList pList){assert(pList);pLinkNode cur = pList->pHead;pLinkNode fcur = NULL;if (cur == NULL){printf("空表\n");return;}else if (cur->next == NULL)   //只有一个结点的情况{free(pList->pHead);pList->pHead = NULL;}else                 //拥有两个以上的结点{while (cur->next != NULL){fcur = cur;cur = cur->next;}fcur->next = NULL;}}void PushFront(pLinkList pList, DataType x){assert(pList);pLinkNode NewNode = BuyNewNode(x);if (pList->pHead == NULL)     //空表的情况{pList->pHead = NewNode;}else{NewNode->next = pList->pHead;pList->pHead = NewNode;}}void PopFront(pLinkList pList){assert(pList);if (pList->pHead == NULL)   //空表{return;}else         //非空{pList->pHead = pList->pHead->next;}}void PrintList(pLinkList pList){assert(pList);pLinkNode cur;cur = pList->pHead;while (cur){printf("%d->", cur->data);cur = cur->next;}printf("NULL");printf("\n");}pLinkNode Find(pLinkList pList, DataType x){assert(pList);pLinkNode cur = pList->pHead;while (cur && (cur->data != x))// 当前结点不为指定数据则指针向后移动{cur = cur->next;}return cur;}void Insert(pLinkList pList, pLinkNode pos, DataType x){assert(pList);pLinkNode cur = pList->pHead;pLinkNode fcur = NULL;pLinkNode NewNode = BuyNewNode(x);if (pos == pList->pHead)  //若指定位置为头结点{NewNode->next = pList->pHead;pList->pHead = NewNode;}else{while (cur && (cur != pos)){fcur = cur;cur = cur->next;}NewNode->next = cur;fcur->next = NewNode;}}void Remove(pLinkList pList, DataType x){assert(pList);pLinkNode cur = pList->pHead;pLinkNode fcur = NULL;if (cur->data == x)      //若指定数据为头结点包含的数据{pList->pHead = pList->pHead->next;}else{while (cur&&(cur->data!=x))  //找到指定数据{fcur = cur;cur = cur->next;}if (cur == NULL)  //若遍历整个链表后没有找到{printf("链表中无该数据\n");}else   //找到了删除{fcur->next = cur->next;free(cur);cur = NULL;}}}void RemoveAll(pLinkList pList, DataType x){assert(pList);pLinkNode cur = pList->pHead;pLinkNode fcur = NULL;pLinkNode del = NULL;if (cur == NULL)      //空表{return;}if ((cur->data == x)&&(cur->next == NULL))  //表中只有一个结点。{free(cur);cur = NULL;}else if (cur->data == x)     //若要删除的数据是头结点{PopFront(pList);}while (cur &&(cur->next))  //循环找到所有指定的数据删除{if(cur->next->data == x){del = cur->next;cur->next = del->next;free(del);del = NULL;}cur = cur->next;}}void Erase(pLinkList pList, pLinkNode pos){assert(pList);pLinkNode cur = pList->pHead;pLinkNode fcur = NULL;if (pos == pList->pHead)  //若指定位置是头结点的位置,调用头删函数{PopFront(pList);}else{while (cur){while (cur != pos)  //循环找到指定位置{fcur = cur;cur = cur->next;}if (cur == NULL){printf("无数据存放在该位置\n");return;}else{fcur->next = cur->next;free(cur);cur = NULL;}}}}void BubbleSort(pLinkList pList){assert(pList);pLinkNode cur = pList->pHead;pLinkNode inCur = pList->pHead;pLinkNode checkNode = NULL;DataType  tmp = 0;int   count = 0;  //用来优化冒泡排序while (cur->next){while (inCur->next != checkNode){if (inCur->data > inCur->next->data){tmp = inCur->data;inCur->data = inCur->next->data;inCur->next->data = tmp;count++;}inCur = inCur->next;}if (count == 0){return;}checkNode = inCur;//j<size-1-i;inCur = pList->pHead;cur = cur->next;}}
主函数部分(主要用来测试):

#include"linklist.h"test1(){LinkList list;InitLinkList(&list);PushBack(&list, 1);PushBack(&list, 2);PushBack(&list, 3);PopBack(&list);PopBack(&list);PrintList(&list);//测试尾插和尾删,应该输出1->NULL;DestroyList(&list);}test2(){LinkList list;pLinkNode ret = NULL;InitLinkList(&list);PushFront(&list, 1);PushFront(&list, 2);PushFront(&list, 3);PopFront(&list);PrintList(&list);  //测试头插和头删,应该输出2->1->NULLret = Find(&list, 1);if (ret == NULL){printf("链表中不存在该数据");}Remove(&list, 1);    PrintList(&list);//测试删除指定数据函数,应该输出2->NULLDestroyList(&list);}test3(){LinkList list;InitLinkList(&list);PushBack(&list, 1);PushBack(&list, 2);PushBack(&list, 3);PushBack(&list, 1);PushBack(&list, 2);PrintList(&list);RemoveAll(&list, 1); //测试指定链表中存在的所有某个数据,调用后应输出2->3->2->NULLPrintList(&list);DestroyList(&list);}test4(){LinkList list;pLinkNode ret = NULL;InitLinkList(&list);PushFront(&list, 1);PushFront(&list, 5);PushFront(&list, 3);PushFront(&list, 7);PushFront(&list, 9);PushFront(&list, 0);PrintList(&list);BubbleSort(&list);  //测试冒泡排序,输出一个无序,调用后输出有序PrintList(&list);DestroyList(&list);}test5(){LinkList list;pLinkNode ret = NULL;InitLinkList(&list);PushFront(&list, 1);PushFront(&list, 2);PushFront(&list, 3);PrintList(&list);ret = Find(&list, 1);if (ret == NULL){printf("链表中不存在该数据");}Insert(&list, ret, 3);   //测试指定位置插入指定数据,调用后输出3->2->3->1->NULL;PrintList(&list);DestroyList(&list);}test6(){LinkList list;pLinkNode ret = NULL;InitLinkList(&list);PushBack(&list, 1);PushBack(&list, 2);PushBack(&list, 3);PrintList(&list);ret = Find(&list, 1);if (ret == NULL){printf("链表中不存在该数据");}Erase(&list, ret); //测试指定位置删除,调用后应输出2->3->NULLPrintList(&list);DestroyList(&list);}int main(){test1();test2();test3();test4();test5();test6();getchar();return 0;}





1 0
原创粉丝点击