博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
数据结构一链表
阅读量:4880 次
发布时间:2019-06-11

本文共 9314 字,大约阅读时间需要 31 分钟。

 

                                                                      无头节点的单链表

链表是一种线性表,但是并不是顺序存储,而是每个节点里面存储着下一个节点的指针,把存储数据元素的数据串链起来。

链表和顺序表的优缺点

  1>.顺序表支持随机访问,单链表不支持随机访问

  2>.顺序表插入/删除数据效率很低时间复杂度为0(N);除尾插尾删效率高,时间复杂度为0(1)

  3>.单链表CPU高速缓存效率低,顺序表的CPU高速缓存效率更高。(因为顺序表的空间一般是连续开辟的,而且一次会开辟存储多个元素的空间,所以在使用顺序表时,可以一次把多个数据写入   高速缓存,再写入主存,顺序表的CPU高速缓存效率更高,且CPU流水线也不会总是被打断;而单链表是每需要存储一个数据才开辟一次空间,所以每个数据存储时都要单独的写入高速缓存区,再写入主存,这样就造成了,单链表CPU高速缓存效率低,且CPU流水线会经常被打断。

单链表的数据结构:

typedef int DataType ;

typedef struct Node

{
         DataType _data ; // 数据
         struct Node* _next; // 指向下一个节点的指针
} Node, *PLinkList ;

 下面是对链表的一些操作

//1、链表的初始化,PSListNode *pHead二级指针,对指向的内容做修改也可以用引用void InitSList(PSListNode *pHead){         *pHead = NULL;}//2、链表的销毁void DestroyList(PSListNode *pHead){    PSListNode cur = pHead;//先保留指向头结点的指针    while (cur)    {        PSListNode temp = cur;        cur = cur->pNext;        free(temp);           }    pHead = NULL;//置空}//3、构造出一个新的节点PSListNode BuyNode(DataType data){    PSListNode temp = (PSListNode)malloc(sizeof(struct SListNode));    assert(temp);    temp->data = data;    temp->pNext = NULL;    return temp;}//尾插(要考虑2种情况,空和非空)void PushBack(PSListNode *pHead, DataType data){    PSListNode tail = *pHead;    //空和非空    if (*pHead == NULL)    {        *pHead = BuyNode(data);    }    else    {         while(tail->pNext!=NULL)        {            tail = tail->pNext;        }        tail->pNext = BuyNode(data);    }}//尾删(3种情况 :空 一个节点 多个节点)void PopBack(PSListNode *pHead){       PSListNode pNode = *pHead;    if (*pHead == NULL)    {        printf("it is empty");        return;    }    else if(pNode->pNext==NULL)    {        free(pNode);        pHead = NULL;    }    else    {        PSListNode tail = *pHead;        PSListNode prevtail = NULL;        while (tail->pNext)        {            prevtail = tail;            tail = tail->pNext;        }        prevtail->pNext = NULL;        free(tail);    }}//头插考虑2种情况(空和非空)void PushFront(PSListNode *pHead,DataType data){    if (NULL == *pHead)    {        *pHead = BuyNode(data);    }    else    {        PSListNode pNode = BuyNode(data);        pNode->pNext =*pHead;        *pHead = pNode;    }}//头删考虑2种情况(空 非空)void PopFront(PSListNode *pHead){
if (NULL == pHead) { return; } else { PSListNode pNode = *pHead; *pHead = pNode->pNext; free(pNode); }}//找节点PSListNode Find(PSListNode *pHead, DataType data){ PSListNode pNode = *pHead; while (pNode) { if (pNode->data == data) { return pNode; } pNode = pNode->pNext; } return NULL;}//删除指定的节点void Erase(PSListNode *pHead, PSListNode pos){ assert(NULL != pHead); assert(NULL!=pos); if (pos == *pHead) { *pHead = pos->pNext; free(pos); } else { PSListNode cur = *pHead; while (cur) { if (cur->pNext ==pos) { cur->pNext = pos->pNext; free(pos); break; } cur = cur->pNext; } }}//插入void Insert(PSListNode *pHead, PSListNode pos, DataType data)//PSListNode pos(指向pos节点的指针){ assert(pos); assert(pHead); if (NULL == *pHead) { return; } PSListNode pNode = BuyNode(data); if (pNode != NULL) { pNode->pNext = pos->pNext; pos->pNext = pNode; }}void PrintListTailToHead(PSListNode pHead){ if (pHead) { PrintListTailToHead(pHead->pNext); printf("%d ", pHead->data); }}void InsertNotHead(PSListNode pos, DataType data){ assert(NULL != pos); PSListNode pNode = BuyNode(pos->data); pNode->pNext = pos->pNext; pos->pNext = pNode; pos->data = data;}void DelNotTailNode(PSListNode pos){ assert(pos && pos->pNext); pos->data = pos->pNext->data; PSListNode*pNode = pos->pNext->pNext; free(pos->pNext); pos->pNext =pNode; }//返回中间节点的指针,2个返回第2个PSListNode FindMidNode(PSListNode pHead){ PSListNode Slow = pHead; PSListNode Fast = pHead; while ((NULL!=Fast)&&(Fast->pNext!=NULL)///************ { Slow = Slow->pNext; Fast = Fast->pNext->pNext; } return Slow;}// 查找链表的倒数第K个结点PSListNode FindLastKNode(PSListNode pHead, int K){ PSListNode pFast = pHead; PSListNode pSlow = pHead; if (pHead == NULL || K <= 0) { return NULL; } while (--K)//先减判断(倒数第一个节点的话slow,fast同步) { if (pFast == NULL)//没有k个节点 { return NULL; } pFast = pFast->pNext; } while (pFast->pNext)//第一个节点,最后一个节点 { pSlow = pSlow->pNext; pFast = pFast->pNext; } return pSlow;}// 合并两个已序单链表PSListNode MergeList(PSListNode pL1, PSListNode pL2){ PSListNode pNode = NULL; PSListNode ptailNode = NULL; PSListNode pnewHead = NULL; PSListNode pL1Node = pL1; PSListNode pL2Node = pL2; if (pL1 == NULL) { return pL2; } if (pL2 == NULL) { return pL1; } if (pL1Node->data < pL2Node->data) { pNode = pL1Node; pL1Node = pL1Node->pNext; } else { pNode = pL1Node; pL2Node = pL2Node->pNext; } pnewHead = pNode; ptailNode = pNode; while (pL1Node&&pL2Node) { if (pL1Node->data < pL2Node->data) { pNode = pL1Node; pL1Node = pL1Node->pNext; } else { pNode = pL2Node; pL2Node = pL2Node->pNext; } ptailNode->pNext = pNode; ptailNode = ptailNode->pNext; } if (pL1Node == NULL) { ptailNode->pNext = pL2Node; } else { ptailNode->pNext = pL1Node; }}// 求环的长度,已知在环内相遇节点从相遇节点开始遍历再回到相遇节点就知道环的长度int GetCyleLen(PSListNode pMeetNode){ int ilen = 1; PSListNode pNode = pMeetNode; if (NULL == pMeetNode) { return 0; } while (pNode->pNext != pMeetNode) { ilen++; } return ilen;} // 单链表排序:冒泡(优化版本)void SortList(PSListNode pHead){ PSListNode ptail = NULL; PSListNode pNode = NULL; PSListNode ppreNode = NULL; if (pHead == NULL||pHead->pNext==NULL) { return; } while (pHead != ptail) { int exchange = 0; ppreNode = pHead; pNode = pHead->pNext; while (pNode != ptail) { if (ppreNode->data > pNode->data) { DataType temp; temp = ppreNode->data; ppreNode->data = pNode->data; pNode->data = temp; exchange = 1; } ppreNode = pNode; pNode = pNode->pNext; } if (exchange == 0)//若第一趟没有交换,有序 { return; } ptail = ppreNode; }}//约瑟夫环问题PSListNode JosephCircle(PSListNode pHead, int M)//多少人{ PSListNode pNode = pHead; PSListNode pdelete = NULL; int k = M; if (NULL == pHead&&M <= 0) { return; } while (pNode->pNext!=pNode) { k = M; while (--k) { pNode = pNode->pNext; } pdelete = pNode->pNext; pNode->data = pdelete->data; pNode->pNext = pdelete->pNext; free(pdelete); }}// 单链表逆置:两种方法都实现:一、三个指针 二、尾插法//1.尾插法void ReverseList(PSListNode* pHead){ assert(NULL != pHead); PSListNode ppreNode = NULL; PSListNode pnewNode = NULL; PSListNode pNode = *pHead; if (*pHead != NULL || (*pHead)->pNext == NULL) { return; } while (pNode) { ppreNode = pNode; pNode = pNode->pNext; ppreNode = pnewNode; pnewNode = ppreNode; }}//2.>三个指针void ReverseList1(PSListNode* pHead){ if (NULL == *pHead || ((*pHead)->pNext) == NULL); { return; } PSListNode ppreNode = NULL; PSListNode pNode =* pHead; while (pNode != NULL) { PSListNode pNext = pNode->pNext; pNode->pNext = ppreNode; ppreNode = pNode; pNode = pNext; } (*pHead) = ppreNode; }// 求环的入口点PSListNode FindEnterNode(PSListNode pHead, PSListNode pMeetNode){ PSListNode pNode = pHead; PSListNode pcur = pMeetNode; if (NULL == pHead || NULL == pMeetNode) { return NULL; } while (pNode != pcur) { pNode = pNode ->pNext; pcur = pcur->pNext; } return pNode;}//判断链表是否带环,快慢指针。如带环总会在环内相遇。PSListNode CheckCycle(PSListNode pHead) { if (NULL == pHead) { return NULL; } PSListNode PSlow = pHead; PSListNode PFast = pHead; while (PFast && PFast->pNext) { PSlow = PSlow->pNext; PFast = PFast->pNext->pNext; if (PSlow == PFast) { return PSlow; } } } int IsListCroseWithCycle(PSListNode pL1, PSListNode pL2) { PSListNode pL1MeetNode = NULL; PSListNode pL2MeetNode = NULL; if (NULL == pL1 || NULL == pL2) { return 0; } pL1MeetNode = CheckCycle(pL1); pL2MeetNode = CheckCycle(pL2); //不带环,遍历2个链表,若尾指针相等,则相交. if (NULL == pL1MeetNode && NULL == pL2MeetNode) { PSListNode pL1Node = pL1; PSListNode pL2Node = pL2; while (pL1Node->pNext != NULL) { pL1Node = pL1Node->pNext; } while (pL2Node->pNext != NULL) { pL2Node = pL2Node->pNext; } if (pL1Node == pL2Node) { return 1; } return 0; } //带环,刚才快慢指针相遇的节点在环内,假如以pL2MeetNode为起点在环内转一圈若可以遇到pL1MeetNode则相交if (pL1MeetNode != NULL && pL2MeetNode != NULL) { PSListNode pNode = pL2MeetNode; while (pNode->pNext != pL2MeetNode) { if (pNode == pL1MeetNode) { return 1; } pNode = pNode->pNext; }return 0; }

 

转载于:https://www.cnblogs.com/Blog-day/p/MY_Blog_Days-8.html

你可能感兴趣的文章
optimizer_dynamic_sampling
查看>>
HTML(WEB)开发day05
查看>>
序列合并求前K小项 POJ2442
查看>>
unity点选构建Mesh并保存OBJ
查看>>
python kmeans实战 - 单机一层聚类(小玩具哦),下次再弄个分布式多次聚类
查看>>
Java主要有那几种文件类型?各自的作用是什么?
查看>>
我的第一个python web开发框架(29)——定制ORM(五)
查看>>
2017.11.18 手把手教你学51单片机-点亮LED
查看>>
xml的创建与解析
查看>>
grep不区分大小写查找字符串方法
查看>>
linux系统灵活运用灯[android课程3]
查看>>
Android 通用Dialog中设置RecyclerView
查看>>
利用 Android Studio 和 Gradle 打包多版本APK
查看>>
Android 自定义标题栏
查看>>
Android 如何把一个 RelativeLayout或ImageView背景设为透明
查看>>
tomcat优化方向
查看>>
http
查看>>
8-1-组队赛
查看>>
codility: CountTriangles
查看>>
赛斯说
查看>>