C语言实现单链表以及链表对应的面试题
来源:互联网 发布:centos查看php版本 编辑:程序博客网 时间:2024/06/06 09:43
//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);//删除第一个出现的dvoid RemoveAll(pList* pplist, DataType d);//删除链表所有dvoid 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->next = 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 RemoveAllvoid 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;}
0 0
- C语言实现单链表以及链表对应的面试题
- c语言链表以及面试题
- C语言实现单链表---面试题详解
- c语言实现单链表基础面试题
- C语言实现单链表常见面试题
- 链表常见面试题-C语言实现
- C语言方面方面的面试题以及答案
- c语言链表的实现、链表部分面试题的解答
- 【c语言】单链表的基础面试题
- c语言的面试题
- 关于数据结构的10个面试题(c语言实现)
- 程序员面试题--堆排序的C语言实现
- C语言实现单链表-面试题(基础篇)
- 单链表相关面试题(C语言实现)
- 一道多线程面试题-C语言实现
- 经典面试题---单链表的基本操作(C语言实现)
- C语言实现单链表的基本操作及其部分面试题
- 关于单链表的一些面试题-基础篇(C语言实现)
- Java知识点小总结(一)
- Service和IntentService与Acticity之间的通信
- nyistOJ-石子合并(一)(区间DP)
- jsonp跨域的简单实现
- java ExecutorService
- C语言实现单链表以及链表对应的面试题
- Call to undefined function mcrypt_module_open()
- 模拟实现memmove
- 又一个乱码问题------ gbk和utf8
- BZOJ 4036 [HAOI2015]按位或
- 列表框的成员函数与使用用例
- 表单提交2次
- linux常用软件安装方法
- Activity