C语言实现单链表面试题--基础篇

来源:互联网 发布:centos系统升级 编辑:程序博客网 时间:2024/06/05 20:00

顺序表和链表的优缺点

顺序表

优点:顺序表是将数据存储在一段连续的内存中,可以通过下标随机访问,效率高。

缺点:插入和删除数据时效率很低,移动数据时需要表里。增容时需要重新开辟内存,有可能造成浪费。

链表

优点:链表在程序运行时动态分配内存,插入和删除速度快。

缺点:不支持随机访问,查找时需要遍历链表。

从各自的优缺点根据使用场景选择。频繁插入、删除使用链表。反之,频繁查找选择顺序表。

void Print_TailToHead(ListNode *pList)//从尾到头打印{if(!pList){printf("NULL");return;}Print_TailToHead(pList->next);printf("->%d", pList->data);}void Erase_Notail(ListNode *pos)//删除一个无头单链表的非尾节点{ListNode *tmp = pos->next;assert((pos) && (pos->next));pos->data = tmp->data;pos->next = tmp->next;free(tmp);}void Insert_Nohead(ListNode *pos, DataType x)//在无头单链表的一个节点前插入一个节点{ListNode *tmp = CreatNode(pos->data);assert(pos);pos->data = x;tmp->next = pos->next;pos->next = tmp;}DataType Josephus(ListNode *pList, int k)//单链表实现约瑟夫环{ListNode *tmp = pList;while(tmp->next){tmp = tmp->next;}tmp->next = pList;while(pList->next != pList){int ret = k;while(--ret){pList = pList->next;}tmp = pList->next;pList->data = tmp->data;pList->next = tmp->next;free(tmp);}return pList->data;}void Severse(ListNode **ppList)//逆置/反转单链表{ListNode *Now = NULL;if((*ppList == NULL)||((*ppList)->next == NULL)){return;}while((*ppList)->next){ListNode *tmp = (*ppList)->next;(*ppList)->next = Now;Now = *ppList;*ppList = tmp;}(*ppList)->next = Now;}void Bubble_sort(ListNode *ppList)//单链表排序(冒泡排序&快速排序){ListNode *p1 = ppList;ListNode *tmp = NULL;if((ppList == NULL) || (ppList->next == NULL)){return;}while(p1 != tmp){ListNode *pList2 = ppList->next;//定义在这里为了防止ppList为空while(pList2 != tmp){if((p1->data)>(pList2->data)){DataType ret = p1->data;p1->data = pList2->data;pList2->data = ret;}p1 = p1->next;pList2 = pList2->next;}tmp = p1;p1 = ppList;pList2 = ppList->next;}}ListNode* Combine(ListNode *pList1, ListNode *pList2)//合并两个有序链表,合并后依然有序{ListNode *head = NULL;ListNode *NowList = NULL;if(pList1 == NULL)return pList2;if(pList2 == NULL)return pList1;if(pList1->data < pList2->data){head = pList1;pList1 = pList1->next;}else{head = pList2;pList2 = pList2->next;}NowList = head;while((pList1!=NULL) && (pList2!=NULL)){if((pList1->data) < (pList2->data)){NowList->next = pList1;pList1 = pList1->next;NowList = NowList->next;}else{NowList->next = pList2;pList2 = pList2->next;NowList = NowList->next;}}if(pList1 == NULL)NowList->next = pList2;elseNowList->next = pList1;return head;}ListNode* Find_MidNode(ListNode *pList)//查找单链表的中间节点,要求只能遍历一次链表{ListNode *fast = pList;//这里当然也可以时pList,但返回值有区别,不信可以验证下ListNode *slow = pList;assert(pList);if((pList == NULL) || (pList->next == NULL))return pList;while((fast->next != NULL) && (fast->next->next != NULL)){fast = fast->next->next;slow = slow->next;}return slow;//当链表个数为偶数时:slow返回中间两个节点的前一个节点,slow->next返回中间节点的后一个节点}ListNode* Find_Rec_k_Node(ListNode *pList, int k)//查找单链表的倒数第k个节点,要求只能遍历一次链表{ListNode *fast = pList;ListNode *slow = pList;assert(pList && k);while(--k){fast = fast->next;if(fast == NULL)return NULL;}while(fast->next != NULL){fast = fast->next;slow = slow->next;}return slow;}

关于链表的所有测试用例

#include "List.h"void test1()//测试PushBack/PopBack{ListNode *List = NULL;PushBack(&List, 1);PushBack(&List, 2);PushBack(&List, 3);PushBack(&List, 4);PrintList(List);Print_TailToHead(List);printf("\n");PopBack(&List);PopBack(&List);PrintList(List);PopBack(&List);PopBack(&List);PrintList(List);}void test2()//测试PushFront/PopFront{ListNode *List = NULL;PushFront(&List, 4);PushFront(&List, 3);PushFront(&List, 2);PushFront(&List, 1);PrintList(List);PopFront(&List);PopFront(&List);PrintList(List);PopFront(&List);PopFront(&List);PrintList(List);}void test3()//测试Insert/Erase{ListNode *List = NULL;ListNode *ret = NULL;PushBack(&List, 1);PushBack(&List, 2);PushBack(&List, 3);PushBack(&List, 4);PrintList(List);ret = Find(List, 4);Insert(&List, ret, 0);PrintList(List);ret = Find(List, 4);Erase(&List, ret);PrintList(List);}void test4()//测试Erase_Notail/Insert_Nohead{ListNode *List = NULL;ListNode *pos = NULL;PushBack(&List, 1);PushBack(&List, 2);PushBack(&List, 3);PushBack(&List, 4);PrintList(List);pos = Find(List, 2);Erase_Notail(pos);PrintList(List);pos = Find(List, 3);Insert_Nohead(pos, 2);PrintList(List);}void test5()//测试Josephus{ListNode *List = NULL;DataType tmp = 0;PushBack(&List, 1);PushBack(&List, 2);PushBack(&List, 3);PushBack(&List, 4);PrintList(List);tmp = Josephus(List, 3);printf("%d\n", tmp);}void test6()//测试Severse/Bubble_sort{ListNode *List = NULL;PushBack(&List, 1);PushBack(&List, 2);PushBack(&List, 3);PushBack(&List, 4);PrintList(List);Severse(&List);PrintList(List);Bubble_sort(List);PrintList(List);}void test7()//测试Combine{ListNode *List1 = NULL;ListNode *List2 = NULL;ListNode *Now = NULL;PushBack(&List1, 3);PushBack(&List1, 3);PushBack(&List1, 6);PushBack(&List2, 1);PushBack(&List2, 2);PushBack(&List2, 2);PushBack(&List2, 7);Now = Combine(List1, List2);PrintList(Now);}void test8()//测试Find_MidNode{ListNode *List = NULL;ListNode *ret = NULL;PushBack(&List, 1);PushBack(&List, 2);PushBack(&List, 3);PushBack(&List, 4);PushBack(&List, 5);PushBack(&List, 6);ret = Find_MidNode(List);printf("%d\n", ret->data);}void test9()//测试Find_Rec_k_Node{ListNode *List = NULL;ListNode *ret = NULL;PushBack(&List, 1);PushBack(&List, 2);PushBack(&List, 3);PushBack(&List, 4);PushBack(&List, 5);PushBack(&List, 6);ret = Find_Rec_k_Node(List, 3);printf("%d\n", ret->data);}void test10()//测试judge_band/judge_band_length/judge_band{ListNode *List = NULL;ListNode *tmp = NULL;ListNode *tail = NULL;PushBack(&List, 1);PushBack(&List, 2);PushBack(&List, 3);PushBack(&List, 4);PushBack(&List, 5);PushBack(&List, 6);tmp = Find(List, 3);tail = Find(List, 6);tail->next = tmp;printf("%p\n", judge_band(List));printf("%d\n", judge_band_length(List));printf("%p\n", Find(List, 3));}void test11()//测试judge_intersect/judge_junction{ListNode *List1 = NULL;ListNode *List2 = NULL;ListNode *p1 = NULL;ListNode *p2 = NULL;PushBack(&List1, 1);PushBack(&List1, 2);PushBack(&List1, 3);PushBack(&List1, 4);PushBack(&List1, 5);PushBack(&List1, 6);p1 = Find(List1, 3);PushBack(&List2, 1);PushBack(&List2, 2);PushBack(&List2, 3);PushBack(&List2, 4);p2 = Find(List2, 4);p2->next = p1;printf("%p\n", judge_intersect(List1, List2));//printf("%p\n", judge_junction(List1, List2));printf("%p\n", Find(List1, 3));}void test12()//测试judge_band_intersect{ListNode *List1 = NULL;ListNode *List2 = NULL;ListNode *p1 = NULL;ListNode *p2 = NULL;PushBack(&List1, 1);PushBack(&List1, 2);PushBack(&List1, 3);PushBack(&List1, 4);PushBack(&List1, 5);PushBack(&List1, 6);p1 = Find(List1, 3);p2 = Find(List1, 6);p2->next = p1;PushBack(&List2, 1);PushBack(&List2, 2);PushBack(&List2, 3);PushBack(&List2, 4);PushBack(&List2, 5);PushBack(&List2, 6);//测试都带环但不相交//p2 = Find(List2, 6);//p1 = Find(List2, 3);//p2->next = p1;//测试都带环且相交p2 = Find(List2, 6);p1 = Find(List1, 5);p2->next = p1;printf("%p\n", judge_band_intersect(List1, List2));printf("%p\n", judge_band(List1));printf("%p\n", judge_band(List2));printf("%p\n", Find(List1, 3));printf("%p\n", Find(List2, 3));}void test13()//测试cpye_dif_List{ListNode *List = NULL;ListNode *NewList = NULL;ListNode *p1 = NULL;ListNode *p2 = NULL;ListNode *p3 = NULL;ListNode *p4 = NULL;ListNode *p5 = NULL;PushBack(&List, 1);PushBack(&List, 2);PushBack(&List, 3);PushBack(&List, 4);PushBack(&List, 5);p1 = Find(List, 1);p2 = Find(List, 2);p3 = Find(List, 3);p4 = Find(List, 4);p5 = Find(List, 5);p1->random = p3;p2->random = p1;p3->random = p3;p4->random = p2;p5->random = p4;NewList = cpye_dif_List(List);PrintList(List);PrintList(NewList);}int main(){//test1();//test2();//test3();//test4();//test5();//test6();//test7();//test8();//test9();//test10();//test11();//test12();//test13();return 0;}


代码是测试过得,如有不对不完善之处,欢迎留言指正.

原创粉丝点击