C语言实现单链表以及链表对应的面试题
2017-03-24 23:52
441 查看
//List.h #define _CRT_SECURE_NO_WARNINGS 1 #ifndef __LIST_H__ #define __LIST_H__ #include<stdio.h> #include<stdlib.h> #include<assert.h> typedef int DataType; typedef struct Node { DataType data; struct Node* next; }Node,*pNode,*pList; void InitList(pList* pplist); //初始化 void PushBack(pList* pplist, DataType d); //尾插 void PushFront(pList* pplist, DataType d);//头插 void PopBack(pList* pplist);//尾删 void PopFront(pList* pplist);//头删 void show(pList plist);//输出 int GetListLength(pList plist);//求链表的长度 pNode Find(pList plist, DataType d);//查找 void Remove(pList* pplist, DataType d);//删除第一个出现的d void RemoveAll(pList* pplist, DataType d);//删除链表所有d void Insert(pList*pplist, pNode pos, DataType d);//在节点前插入元素 void Erase(pList* pplist, pNode pos);// 删除当前节点 void DestroyList(pList *pplist);//销毁链表 //链表面试题 void EraseNotTail(pNode pos); //删除一个无头非尾节点 void InsertFrontNode(pNode pos, DataType d); //在一个无头单链表的非头结点前插入一个元素 void Reverselist(pList *pplist); //将单链表逆序 pList Merge(pList L1, pList L2); //合并两个有序链表 pList Merge2(pList L1, pList L2); //合并两个有序链表 pNode FindMidNode(pList list); //查找链表中间节点 void DelkNode(pList* pplist, int k); //删除链表倒数第k的元素 pNode JosephCycle(pList *pplist, int sum); //约瑟夫环问题 pNode CheckCycle(pList plist); //检查是否带环 int GetCycleLength(pNode meet); //求环的长度 pNode GetCycleEntryNode(pList plist, pNode meetNode); //求环的入口地址 void PrintReversely(pList plist); //逆序打印单链表 int CheckCross(pList list1, pList list2); //检查两个单链表是否相交 #endif
//List.c #define _CRT_SECURE_NO_WARNINGS 1 #include"List.h" void InitList(pList* pplist) { assert(pplist); *pplist = NULL; } pNode BuyNode(DataType d) { pNode pnode = (pNode)malloc(sizeof(Node)); if (pnode == NULL) { perror("malloc"); return NULL; } pnode->data = d; pnode->next = NULL; return pnode; } void PushBack(pList* pplist, DataType d) { assert(pplist); pNode NewNode = BuyNode(d); if (*pplist == NULL) //无节点 { *pplist = NewNode; } else //有节点 { pNode cur = *pplist; while (cur->next) { cur = cur->next; } cur->next = NewNode; } } void PushFront(pList* pplist, DataType d) { assert(pplist); pNode NewNode = BuyNode(d); if (*pplist == NULL)//无节点 { *pplist = NewNode; } else//有节点 { NewNode->next = *pplist; *pplist = NewNode; } } void PopBack(pList* pplist) { pNode cur = *pplist; pNode del = NULL; assert(pplist); if (*pplist == NULL)//无节点 { printf("链表为空\n"); return; } else if (cur->next==NULL) //有一个节点 { free(cur); *pplist = NULL; } else //多个节点 { while (cur->next) //找倒数第二个元素 { del = cur; cur=cur->next; } free(cur); del->next = NULL; } } void PopFront(pList* pplist) { pNode cur = *pplist; assert(pplist); if (*pplist == NULL)//无节点 { printf("链表为空\n"); return; } else if (cur->next == NULL)//有一个节点 { free(cur); *pplist = NULL; } else//多个节点 { *pplist = cur->next; free(cur); } } void show(pList plist) { if (plist == NULL) { printf("链表为空\n"); return; } pNode cur = plist; printf("list:"); while (cur) { printf("%d->", cur->data); cur = cur->next; } printf("NULL\n"); } int GetListLength(pList plist) { pNode cur = plist; int count = 0; while (cur) { cur = cur->next; count++; } return count; } pNode Find(pList plist, DataType d) { pNode cur = plist; while (cur) { if (cur->data == d) { return cur; } cur = cur->next; } return NULL; } void Remove(pList* pplist, DataType d) //删除第一个出现的d { assert(pplist); pNode cur = *pplist; pNode del = NULL; while (cur) { if (cur->data == d) { if (*pplist == cur) { *pplist = cur->next;//要删除的是第一个节点 } else { del->next = cur->next;//cur的上一个指向下一个 } free(cur); return;//这里必须结束不然下面del=cur;程序就会崩溃 } del = cur; //作用保存cur上一个元素的地址 cur = cur->next; } } void RemoveAll(pList* pplist, DataType d)//删除链表的所有d元素 { assert(pplist); pNode cur = *pplist; pNode tmp= NULL; pNode del = NULL; while (cur) { tmp = cur;//保存cur的地址 if (cur->data == d) { if (*pplist == cur) { *pplist = cur->next;//要删除的是第一个节点 } else { del->next = cur->next; } cur = del;//删除后让cur保存cur上一个元素的地址 free(tmp); } del = cur;//作用保存cur上一个元素的地址 cur = cur->next; } } void Insert(pList*pplist, pNode pos, DataType d) { assert(*pplist); assert(pos); pNode NewNode = BuyNode(d); pNode cur = *pplist; if (pos == cur) //头节点 { NewNode->next = *pplist; *pplist = NewNode; } else { while (cur->next!=pos)//找到pos前一个节点 { cur = cur->next; } NewNode->next = pos; cur->next = NewNode; } } void Erase(pList* pplist, pNode pos) { assert(pplist); assert(pos); pNode cur = *pplist; pNode del = NULL; //if (cur == NULL) //{ // printf("链表为空无法删除\n"); // return; //} //if (cur == pos) //头结点 //{ // *pplist = cur->next; // free(cur); //} //else //{ // while (cur->next!=pos) // { // cur = cur->next; // } // cur->next = pos->next; // free(pos); //} if (pos->next == NULL) { PopBack(pplist); return NULL; } pos->data = pos->next->data;//相当于删除下个元素把下一个元素的值给pos del = pos->next;//del保存下个元素的地址 pos->next = pos->next->next; free(del); } void DestroyList(pList *pplist) { pNode cur = *pplist; while (cur) { pNode del = cur; cur = cur->next; free(del); } *pplist = NULL; } void EraseNotTail(pNode pos) //删除一个无头非尾节点 { assert(pos->next); pNode cur = pos->next; pos->data = pos->next->data; pos ->next = pos->next->next; free(cur); } void InsertFrontNode(pNode pos, DataType d) //在一个无头单链表的非头结点前插入一个元素 { pNode NewNode = BuyNode(d); DataType tmp = 0; NewNode->next = pos->next;//将元素插入pos后边 pos->next = NewNode; tmp = pos->data; //然后将pos的值和d相交换 pos->data = NewNode->data; NewNode->data = tmp; } void Reverselist(pList *pplist) //将单链表逆序 { assert(pplist); pNode cur = *pplist; pNode tmp = NULL; pList NewList = NULL; while (cur) { tmp = cur; cur = cur->next; tmp->next = NewList; NewList = tmp; } *pplist = NewList; } pList Merge(pList L1, pList L2) //合并两个有序链表 { pList NewList = NULL; pNode tail = NULL; if (L1 == L2)//如果两个相等返回任意一个 { return L1; } if (L1 == NULL)//一个为空 返回另一个 { return L2; } if (L2 == NULL) { return L1; } if (L1->data <= L2->data) //头结点 { NewList = L1; L1 = L1->next; } else { NewList = L2; L2 = L2->next; } tail = NewList; while (L1&&L2) { if (L1->data <= L2->data) { tail->next = L1; tail = L1; L1 = L1->next; } else { tail->next = L2; tail = L2; L2 = L2->next; } } if (L1 == NULL) { tail->next = L2; } if (L2 == NULL) { tail->n 11fae ext = L1; } return NewList; } pList Merge2(pList L1, pList L2) //合并两个有序链表采用递归调用 { pList NewList = NULL; if (L1 == L2) { return L1; } if (L1 == NULL) { return L2; } if (L2 == NULL) { return L1; } if (L1->data <= L2->data) { NewList = L1; NewList->next = Merge2(L1->next, L2); } else { NewList = L2; NewList->next = Merge2(L2->next, L1); } return NewList; } pNode FindMidNode(pList list) //查找链表中间节点 { pNode fast = list; //快指针 pNode slow = list; //慢指针 while (fast&&fast->next) { slow = slow->next; fast = fast->next->next; } return slow; } void DelkNode(pList* pplist, int k) //删除链表倒数第k的元素 { assert(pplist); pNode fast = *pplist;//快指针 pNode slow = *pplist; //慢指针 while (fast) { k--; if (k < 0) { slow = slow->next; } fast = fast->next; //让快指针多走k步 }//然后当快指针下一个为空时慢指针刚好指向倒数第k的元素 pNode cur = slow->next; slow->data = cur->data; slow->next = cur->next; free(cur); } pNode JosephCycle(pList *pplist, int sum) //约瑟夫环问题 { assert(pplist); int i = 0; pNode cur = *pplist; while ((cur->next) != cur) { if (cur->next == cur) { break; } for (i = 0; i < sum-1; i++) { cur = cur->next; } printf("%d ", cur->data); pNode del = cur->next; cur->data = cur->next->data; cur->next = cur->next->next; free(del); } return cur; } pNode CheckCycle(pList plist) //检查是否带环 { pNode fast = plist; pNode slow = plist; while (fast&&fast->next) { fast = fast->next->next;//快指针走两步 slow = slow->next;//慢指针走一步 if (fast == slow) { return slow;// 当快慢相遇就返回这个元素地址 } } return NULL; } int GetCycleLength(pNode meet) //求环的长度 { int count = 0; pNode cur = meet; do { cur = cur->next; ++count; } while (cur != meet); return count; } pNode GetCycleEntryNode(pList plist, pNode meetNode) //求环的入口地址 { pNode cur = plist; while (cur != meetNode) { cur = cur->next; meetNode = meetNode->next; } return cur; } void PrintReversely(pList plist) //逆序打印单链表 { pNode cur = plist; if (plist == NULL) { return ; } if (cur != NULL) //递归调用 { PrintReversely(cur->next); } printf("%d ", cur->data); } int CheckCross(pList list1, pList list2) //检查两个单链表是否相交 { pNode cur1 = list1; pNode cur2 = list2; if (cur1==NULL||cur2==NULL) { return 0; } while (cur1) { cur1 = cur1->next; } while (cur2) { cur2 = cur2->next; } if (cur1 == cur2) return 1; return 0; }
Test.c #define _CRT_SECURE_NO_WARNINGS 1 #include"List.h" //测试尾插以及尾删 void test1() { pList list = NULL; InitList(&list); PushBack(&list, 2); PushBack(&list, 4); PushBack(&list, 5); PushBack(&list, 7); PopBack(&list); PopBack(&list); PopBack(&list); PopBack(&list); PopBack(&list); } //测试头插以及头删 void test2() { pList list = NULL; InitList(&list); PushFront(&list, 1); PushFront(&list, 2); PushFront(&list, 3); PushFront(&list, 4); PushFront(&list, 5); PopFront(&list); PopFront(&list); PopFront(&list); PopFront(&list); PopFront(&list); PopFront(&list); } //测试输出以及链表长度 void test3() { pList list = NULL; InitList(&list); PushFront(&list, 1); PushFront(&list, 2); PushFront(&list, 3); PushFront(&list, 4); PushFront(&list, 5); int ret = GetListLength(list); printf("%d\n", ret); show(list); } //测试Remove RemoveAll void test4() { pList list = NULL; InitList(&list); PushBack(&list, 2); PushBack(&list, 4); PushBack(&list, 5); PushBack(&list, 8); PushBack(&list, 5); PushBack(&list, 5); PushBack(&list, 7); PushBack(&list, 6); show(list); Remove(&list, 5); show(list); RemoveAll(&list, 5); show(list); } //测试合并两个有序链表 void TestMerge() { pList list = NULL; pList List = NULL; pList NewList = NULL; InitList(&list); InitList(&List); InitList(&NewList); PushBack(&list, 2); PushBack(&list, 4); PushBack(&list, 5); PushBack(&list, 7); PushBack(&List, 1); PushBack(&List, 3); PushBack(&List, 5); PushBack(&List, 8); show(list); show(List); NewList = Merge2(list, List); show(NewList); pNode cur = NULL; cur = FindMidNode(NewList); printf("%d", cur->data); } //测试约瑟夫环问题 void TestJosephCycle() { pList list = NULL; InitList(&list); PushBack(&list, 1); PushBack(&list, 2); PushBack(&list, 3); PushBack(&list, 4); PushBack(&list, 5); Find(list, 5)->next = Find(list, 1); pNode ret=JosephCycle(&list, 3); printf("%d\n", ret->data); } //测试链表长度 void TestGetCycleLength() { pList list = NULL; InitList(&list); PushBack(&list, 1); PushBack(&list, 2); PushBack(&list, 3); PushBack(&list, 4); PushBack(&list, 5); Find(list, 5)->next = Find(list, 1); pNode ret = CheckCycle(list); int tmp = GetCycleLength(ret); printf("%d\n", tmp); } //测试检查是否带环 void TestCheckCycle() { pList list = NULL; InitList(&list); PushBack(&list, 1); PushBack(&list, 2); PushBack(&list, 3); PushBack(&list, 4); PushBack(&list, 5); //Find(list, 5)->next = Find(list, 3); pNode ret = CheckCycle(list); if (ret == NULL) { printf("不带环\n"); } else { printf("%d\n", ret->data); } } //测试环的入口地址 void TestGetCycleEntryNode() { pList list = NULL; InitList(&list); PushBack(&list, 1); PushBack(&list, 2); PushBack(&list, 3); PushBack(&list, 4); PushBack(&list, 5); PushBack(&list, 6); PushBack(&list, 7); PushBack(&list, 8); Find(list, 8)->next = Find(list, 3); pNode ret = CheckCycle(list); pNode tmp = GetCycleEntryNode(list, ret); printf("%d\n", tmp->data); } //测试逆序打印单链表 void TestPrintReversely() { pList list = NULL; InitList(&list); PushBack(&list, 1); PushBack(&list, 2); PushBack(&list, 3); PushBack(&list, 4); PushBack(&list, 5); PrintReversely(list); } //测试两个单链表是否相交 void TestCheckCross() { pList list = NULL; pList List = NULL; InitList(&list); InitList(&List); PushBack(&list, 2); PushBack(&list, 4); PushBack(&list, 5); PushBack(&list, 7); PushBack(&List, 1); PushBack(&List, 3); PushBack(&List, 5); PushBack(&List, 8); Find(List, 8)->next = Find(list, 5); show(list); show(List); int ret = CheckCross(list, List); if (ret == 1) { printf("相交\n"); } if (ret == 0) { printf("不相交\n"); } } int main() { //test1(); //test2(); //test3(); test4(); //TestMerge(); //TestList(); //TestJosephCycle(); //TestCheckCycle(); //TestGetCycleLength(); //TestGetCycleEntryNode(); //TestCheckCross(); //TestPrintReversely(); //TestComplexList(); return 0; }
相关文章推荐
- C语言单向动态链表程序,实现链表的建立,合并,重新排序,链表元素的插入与删除,以及根据元素成员的值进行元素删除。
- C语言实现单链表,单链表面试题面试
- C语言实现链表之单向链表(十三)获取数据对应的结点
- C语言实现单链表常见面试题
- 【c语言】链表的实现、链表部分面试题的解答
- 对线性表理解以及C语言实现链表的插入删除等操作。
- C语言实现无头单链表及链表相关面试题(重点!)
- C语言实现单链表的基本操作及其部分面试题
- 链表的c语言实现以及根据linux内核中链表的实现过程
- C语言实现单链表的基本操作及其部分面试题
- 链表的c语言实现以及根据linux内核中链表的实现过程
- C语言实现单链表-面试题(基础篇)
- c语言实现链表面试题
- 单链表的实现和相关面试题及其详解(C语言)
- 《剑指offer》面试题57 删除链表中重复的结点 C++ 实现 以及 错误总结 (指针问题)!!
- 经典面试题---单链表的基本操作(C语言实现)
- C语言实现链表之双向链表(十三)获取数据对应的结点
- C语言中链表节点的实现,以及如何实现泛型
- 自杀环---约瑟夫环(单链表经典面试题)------>C语言实现
- 线性链表的表示以及实现(C语言编写)