单链表
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单链表相关的知识,希望对你有一定的参考价值。
单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。
1、链接存储方法
链接方式存储的线性表简称为链表(LinkList)。
链表的具体存储表示为:
① 用一组任意的存储单元来存放线性表的结点(这组存储单元既可以是连续的,也可以是不连续的)
② 链表中结点的逻辑次序和物理次序不一定相同。为了能正确表示结点间的逻辑关系,在存储每个结点值的同时,还必须存储指示其后继结点的地址(或位置)信息(称为指针(pointer)或链(link))
注意:
链式存储是最常用的存储方式之一,它不仅可用来表示线性表,而且可用来表示各种非线性的数据结构。
2、链表的结点结构
┌───┬───┐
│data │next │
└───┴───┘
data域--存放结点值的数据域
next域--存放结点的直接后继的地址(位置)的指针域(链域)
//功能 //LinkList.h #pragma once #include <stdio.h> #include <stdlib.h> #include <assert.h> typedef int DataType; typedef struct LinkNode //节点 = 数据 + 指向下一个节点的指针 { DataType data; struct LinkNode *next; }LinkNode,*pLinkNode,*pLinkList; void InitLinkList(pLinkList* pHead); //初始化链表 void Destroy(pLinkList* pHead); //销毁链表 pLinkNode BuyNode(DataType x); //创建一个节点 void PushBack(pLinkList *pHead, DataType x); //尾插 void PopBack(pLinkList *pHead); //尾删 void PushFront(pLinkList *pHead, DataType x); // 头插 void PopFront(pLinkList *pHead); //头删 void PrintList(pLinkList List); //打印链表 int GetListLength(pLinkList Head); //求取链表长度 pLinkNode Find(pLinkList Head, DataType x); //找指定元素x void Insert(pLinkList *pHead, pLinkNode pos, DataType x); //在指定位置pos插入指定元素x void Erase(pLinkList *pHead, pLinkNode pos); //删除指定位置pos元素 void Remove(pLinkList* pHead, DataType x); //删除指定元素x void RemoveAll(pLinkList* pHead, DataType x); //删除所有的指定元素x void EraseNotTail(pLinkNode pos); // 删除无头链表的非尾节点 void ReverseList(pLinkNode *pHead); // 逆序链表 void BubbleSort(pLinkList *pHead); //排序链表(冒泡) void InsertFrontNode(pLinkNode pos, DataType x); //在当前节点前插入一个数据x pLinkNode Merge(pLinkList list1, pLinkList list2); //合并两个有序链表 pLinkNode JosephCycle(pLinkList* pHead, int num); //约瑟夫环 pLinkNode FindMidNode(pLinkList pHead); //查找链表的中间节点---7 // 删除单链表的倒数第k个节点(k > 1 && k < 链表的总长度)----9 // 时间复杂度O(N) void DelKNode(pLinkList *pHead, int k); // 【链表带环问题】-----10 // 判断链表是否带环, 若链表带环则求环的长度和相遇节点,不带环返回-1 pLinkNode CheckCycle(pLinkList pList); int GetCircleLength(pLinkNode meet); // 获取环入口点 pLinkNode GetCycleEntryNode(pLinkList list, pLinkNode meetNode); // 【链表相交问题】 // // 判断两个链表是否相交,假设两个链表都不带环。 // int CheckCross(pLinkList list1, pLinkList list2);
//功能实现 //LinkList.c #include "LinkList.h" void InitLinkList(pLinkList* pHead) //初始化链表 { assert(pHead); *pHead = NULL; } void Destroy(pLinkList* pHead) //销毁链表 { pLinkNode cur = *pHead; assert(pHead); if(*pHead == NULL) { return; } else { while(cur) { pLinkNode del = cur; cur = cur->next; free(del); del = NULL; } } } pLinkNode BuyNode(DataType x) //创建一个节点 { pLinkNode NewNode = (pLinkNode)malloc(sizeof(LinkNode)); NewNode->data = x; NewNode->next = NULL; return NewNode; } void PushBack(pLinkList *pHead, DataType x) //尾插 { pLinkNode NewNode = BuyNode(x); pLinkNode cur = *pHead; assert(pHead); if(cur == NULL) { *pHead = NewNode; } else { while(cur->next) { cur = cur->next; } cur->next = NewNode; } } void PopBack(pLinkList* pHead)//尾删 { pLinkNode cur = *pHead; assert(pHead); //没有节点 if(*pHead == NULL) { return; } //一个节点 else if((*pHead)->next == NULL) { free(*pHead); *pHead = NULL; } //两个及以上 else { pLinkNode del; while(cur->next->next) { cur = cur->next; } del = cur->next; cur->next = NULL; free(del); del = NULL; } } void PushFront(pLinkList *pHead, DataType x) //头插 { pLinkNode NewNode = BuyNode(x); assert(pHead); if(*pHead == NULL) { *pHead = NewNode; } else { NewNode->next = *pHead; *pHead = NewNode; } } void PopFront(pLinkList *pHead) //头删 { assert(pHead); if(*pHead == NULL) { return; } else { pLinkNode del = *pHead; *pHead = (*pHead)->next; free(del); del = NULL; } } void PrintList(pLinkList List) //打印链表 { pLinkNode cur = (pLinkNode)List; printf("List is:"); while(cur) { printf("%d->",cur->data); cur = cur->next; } printf("over\n"); } int GetListLength(pLinkList Head) //求取链表长度 { int count = 0; pLinkList cur = Head; assert(Head); while(cur) { count++; if(cur->next == NULL) { return count; } cur = cur->next; } return count; } pLinkNode Find(pLinkList Head, DataType x) //查找指定元素x的位置 { pLinkList cur = Head; assert(Head); while(cur) { if(cur->data == x) { return (pLinkNode)cur; } cur = cur->next; } return NULL; } void Insert(pLinkList *pHead, pLinkNode pos, DataType x) //指定位置pos插入元素x { pLinkNode cur = *pHead; pLinkNode NewNode =BuyNode(x); assert(pHead); assert(pos); while(cur->next != pos) { cur = cur->next; } NewNode->next = cur->next; cur->next = NewNode; } void Erase(pLinkList *pHead, pLinkNode pos) //删除pos位置元素 { pLinkNode cur = *pHead; pLinkNode del = NULL; pLinkNode prev = NULL; //cur的前一个节点 assert(pHead); assert(pos); if (cur == NULL) { printf("List is empty!!\n"); return; } while(cur) { del = cur; if (cur == pos) { //没有节点 if(cur == *pHead) { *pHead = (*pHead)->next; } //一个及以上节点 else { prev->next = cur->next; } free(del); del = NULL; break; //删除完成后,跳出Erase() } prev = cur; cur = cur->next; } } void Remove(pLinkList* pHead, DataType x) //删除元素x { pLinkNode cur = *pHead; pLinkNode del = NULL; pLinkNode prev = NULL;//cur的前一个节点 assert(pHead); if(cur == NULL) { printf("List is empty!!\n"); return; } while(cur) { del = cur; if(cur->data == x) { //没有节点 if(cur == *pHead) { *pHead = (*pHead)->next; } //一个及以上节点 else { prev->next = cur->next; } free(del); del = NULL; break; //只删除一次,删除后跳出Remove() } prev = cur; cur = cur->next; } } void RemoveAll(pLinkList* pHead, DataType x) //删除所有的元素x { pLinkNode cur = *pHead; pLinkNode del = NULL; pLinkNode prev = NULL; //cur的前一个节点 assert(pHead); if(cur == NULL) { printf("List is empty!!\n"); return; } while(cur) { del = cur; if(cur->data == x) { //没有节点 if(cur == *pHead) { *pHead = (*pHead)->next; cur = *pHead; } //一个及以上节点 else { prev->next = cur->next; cur = prev->next; } free(del); del = NULL; } else { prev = cur; cur = cur->next; } } } void EraseNotTail(pLinkNode pos) // 删除无头链表的非尾节点 { pLinkNode del = NULL; assert(pos); /*替换删除*/ pos->data = pos->next->data; //将要删除节点的数据用他下一个节点的数据进行替换 del = pos->next; pos->next = del->next; free(del); //删除下一个节点 del = NULL; } void ReverseList(pLinkList* pHead) // 逆序链表 { pLinkNode cur = *pHead; pLinkNode prev = NULL; pLinkNode pNewHead = NULL; assert(pHead); if(pHead == NULL) /*空链表*/ { printf("List is empty!!\n"); return; } else if((*pHead)->next == NULL) /*一个节点*/ { return; } else { while(cur != NULL) { prev = cur; cur = cur->next; prev->next = pNewHead; pNewHead = prev; } *pHead = pNewHead; // *pHead指向新的头结点 } } void BubbleSort(pLinkList *pHead) //排序链表(冒泡) { pLinkNode cur = *pHead; pLinkNode end = NULL; assert(pHead); while(cur != end) //冒泡的次数 { while(cur && (cur->next != end)) //一次冒泡 ,最大的数放到末尾 { if(cur->data > cur->next->data) //交换数据 { DataType tmp = cur->data; cur->data = cur->next->data; cur->next->data = tmp; } cur = cur->next; } end = cur; //记住最大数的位置 cur = *pHead; } } void InsertFrontNode(pLinkNode pos, DataType x) //在当前节点前插入一个数据x { pLinkNode NewNode = BuyNode(x); DataType tmp; assert(pos); NewNode->next = pos->next; //替换插入 pos->next = NewNode; tmp = pos->data; //交换数据 pos->data = NewNode->data; NewNode->data = tmp; } pLinkNode Merge(pLinkList list1, pLinkList list2) //合并两个有序链表 { pLinkNode NewHead = NULL; pLinkNode cur = NULL; if(list1 == list2) //两个链表相等 { return list1; } if((list1 == NULL) && (list2 != NULL)) { return list2; //list1为空 } if((list1 != NULL) && (list2 == NULL)) { return list1; //list2为空 } /*确定头结点*/ if(list1->data > list2->data) { NewHead = list2; list2 = list2->next; } else { NewHead = list1; list1 = list1->next; } cur = NewHead; while((list1) && (list2)) { if(list1->data > list2->data) { cur->next = list2; list2 = list2->next; } else { cur->next = list1; list1 = list1->next; } cur = cur->next; } /*至少一个链表此时为空,将不为空的连接在新链表的后面*/ if(list1) { cur->next = list1; } else { cur->next = list2; } return NewHead; } pLinkNode _Merge(pLinkList list1, pLinkList list2) //合并两个有序链表(递归) { pLinkNode NewHead = NULL; if(list1 == list2) //两个链表相等 { return list1; } else if((list1 == NULL) && (list2 != NULL)) { return list2; //list1为空 } else if((list1 != NULL) && (list2 == NULL)) { return list1; //list2为空 } if(list1->data >list2->data) { NewHead = list2; NewHead->next = _Merge(list1, list2->next); //递归调用 } else { NewHead = list1; NewHead->next = _Merge(list1->next, list2); //递归调用 } return NewHead; } pLinkNode JosephCycle(pLinkList* pHead, int num) //约瑟夫环 { pLinkNode del = NULL; pLinkNode cur = *pHead; int count = 0; assert(pHead); while(1) { count = num; if(cur->next == cur) //结束条件 { break; } while(--count) { cur = cur->next; } printf("%d ",cur->data); del = cur->next; cur->next = del->next; cur->data = del->data; free(del); del = NULL; } *pHead = cur; printf("\n"); return cur; } pLinkNode FindMidNode(pLinkList pHead) //查找链表的中间节点 { pLinkNode Fast = pHead; pLinkNode Slow = pHead; assert(pHead); if(pHead == NULL) { printf("List is empty!!\n"); return NULL; } while(Fast && Fast->next) { Fast = Fast->next->next; Slow = Slow->next; } return Slow; } void DelKNode(pLinkList *pHead, int k) //删除单链表的倒数第k个节点(k > 1 && k < 链表的总长度) { pLinkNode first = *pHead; pLinkNode second = *pHead; pLinkNode del =NULL; assert(k>1); //快指针先走k步 while(--k) { //判断k是否合法(k小于链表长度) if(k != 0) { if(first == NULL) { printf("Please enter legal (k)!!\n"); return; } } first = first->next; } //快慢指针一起走 while(first && first->next) { first = first->next; second = second->next; } //替换删除 del = second->next; second->data = del->data; second->next = del->next; free(del); del = NULL; } pLinkNode CheckCycle(pLinkList pList) //判断链表是否带环 { pLinkNode Fast = pList; pLinkNode Slow = pList; assert(pList); while(Fast && Fast->next) { Fast = Fast->next->next; Slow = Slow->next; if(Fast == Slow) //判断是否带环 { return Fast; } } return NULL; } int GetCircleLength(pLinkNode meet) //链表带环则求环的长度和相遇节点,不带环返回-1 { pLinkNode cur = meet; int count = 0; do { cur = cur->next; count++; }while(cur != meet); return count; } pLinkNode GetCycleEntryNode(pLinkList list, pLinkNode meetNode) // 获取环入口点 { pLinkNode Entry = list; pLinkNode Meet = meetNode; while(Entry != Meet) { Entry = Entry->next; Meet = Meet->next; } return Entry; } // 【链表相交问题】 // //判断两个链表是否相交,假设两个链表都不带环。 // int CheckCross(pLinkList list1, pLinkList list2) { pLinkNode first = list1; pLinkNode second = list2; if((first == NULL)||(second == NULL)) { return -1; } while(first->next) { first = first->next; } while(second->next) { second->next; } if(first == second) { return 1; } else { return -1; } }
//测试 //test.c #include "LinkList.h" void test() { pLinkList MyList; pLinkNode rec = NULL; int ret = 0; InitLinkList(&MyList); PushBack(&MyList,1); PushBack(&MyList,2); PushBack(&MyList,3); PrintList(MyList); PopBack(&MyList); PrintList(MyList); PushFront(&MyList, 4); PrintList(MyList); PopFront(&MyList); PrintList(MyList); ret = GetListLength(MyList); printf("ret = %d\n",ret); rec = Find(MyList, 2); if(rec == NULL) printf("表中没有此元素!!\n"); else printf("rec = %d\n", rec->data); Insert(&MyList, rec, 6); PrintList(MyList); Erase(&MyList, rec); PrintList(MyList); Remove(&MyList, 6); PrintList(MyList); Remove(&MyList, 1); PrintList(MyList); PushBack(&MyList,1); PushBack(&MyList,2); PushBack(&MyList,1); PushBack(&MyList,3); PushBack(&MyList,1); PrintList(MyList); RemoveAll(&MyList, 1); PrintList(MyList); Destroy(&MyList); } //BubbleSort() void test2() { pLinkList MyList; pLinkNode ret = NULL; InitLinkList(&MyList); PushBack(&MyList,1); PushBack(&MyList,2); PushBack(&MyList,3); PrintList(MyList); ret = Find(MyList, 2); EraseNotTail(ret); PrintList(MyList); //PushBack(&MyList,3); PushBack(&MyList,4); PushBack(&MyList,5); PrintList(MyList); ReverseList(&MyList); PrintList(MyList); BubbleSort(&MyList); PrintList(MyList); Destroy(&MyList); } //InsertFrontNode() void test3() { pLinkList MyList; pLinkNode ret = NULL; InitLinkList(&MyList); PushBack(&MyList,1); PushBack(&MyList,2); PushBack(&MyList,3); PrintList(MyList); ret = Find(MyList, 2); printf("ret->data = %d\n",ret->data); InsertFrontNode(ret, 4); PrintList(MyList); Destroy(&MyList); } //Merge() , _Merge() void test4() { pLinkList list1; pLinkList list2; pLinkNode NewList = NULL; InitLinkList(&list1); InitLinkList(&list2); PushBack(&list1,1); PushBack(&list1,3); PushBack(&list1,4); PrintList(list1); PushBack(&list2,2); PushBack(&list2,5); PushBack(&list2,6); PrintList(list2); NewList = _Merge(list1,list2); PrintList(NewList); Destroy(&NewList); } //JosephCycle() void test5() { pLinkList MyList; pLinkNode ret = NULL; int i = 0; InitLinkList(&MyList); for(i=1; i<=41; i++) { PushBack(&MyList, i); } //创建环 ret = Find(MyList, 41); ret->next = MyList; ret = JosephCycle(&MyList, 3); printf("ret = %d\n", ret->data); //结环,销毁空间 ret->next = NULL; free(ret); ret = NULL; } //FindMidNode() void test6() { pLinkList MyList; pLinkNode ret = NULL; InitLinkList(&MyList); PushBack(&MyList, 1); PushBack(&MyList, 2); PushBack(&MyList, 3); PushBack(&MyList, 4); PushBack(&MyList, 5); PushBack(&MyList, 6); PrintList(MyList); ret = FindMidNode(MyList); printf("ret = %d\n", ret->data); Destroy(&MyList); } //DelKNode() void test7() { pLinkList MyList; pLinkNode ret = NULL; InitLinkList(&MyList); PushBack(&MyList, 1); PushBack(&MyList, 2); PushBack(&MyList, 3); PushBack(&MyList, 4); PushBack(&MyList, 5); PushBack(&MyList, 6); PrintList(MyList); DelKNode(&MyList, 8); PrintList(MyList); Destroy(&MyList); } //CheckCycle() , GetCircleLength() ,GetCycleEntryNode() void test8() { pLinkList MyList; pLinkNode ret1 = NULL; pLinkNode ret2 = NULL; pLinkNode ret = NULL; pLinkNode entry = NULL; int i = 0; InitLinkList(&MyList); for(i=1; i<=7; i++) { PushBack(&MyList, i); } //创建环 ret1 = Find(MyList, 4); ret2 = Find(MyList, 7); ret2->next = ret1; ret = CheckCycle(MyList); if(ret == NULL) //不带环 { printf("LinkList not cycle!!\n"); } else //带环 { printf("LinkList is cycle!!\n"); } entry = GetCycleEntryNode(MyList, ret); printf("EntyrNode = %d\n", entry->data); printf("CircleLength = %d\n",GetCircleLength(ret)); ret2->next = NULL; //解环 Destroy(&MyList); } int main() { //test(); //test2(); //test3(); test4(); //test5(); //test6(); //test7(); //test8(); system("pause"); return 0; }
本文出自 “Pzd流川枫” 博客,请务必保留此出处http://xujiafan.blog.51cto.com/10778767/1747968
以上是关于单链表的主要内容,如果未能解决你的问题,请参考以下文章