单链表基础面试题

来源:互联网 发布:淘宝旺旺号在哪里登录 编辑:程序博客网 时间:2024/06/05 06:36
1.比较顺序表和链表的优缺点,说说它们分别在什么场景下使用?
2.从尾到头打印单链表
3.删除一个无头单链表的非尾节点
4.在无头单链表的一个节点前插入一个节点
5.单链表实现约瑟夫环
6.逆置/反转单链表
7.单链表排序(冒泡排序&快速排序)
8.合并两个有序链表,合并后依然有序
9.查找单链表的中间节点,要求只能遍历一次链表

10.查找单链表的倒数第k个节点,要求只能遍历一次链表                  


解答: 

1.比较顺序表和链表的优缺点,说说它们分别在什么场景下使用? 

 顺序表:顺序表的地址空间是连续的,空间利用不充分。 查找速度快,便于大量元素的查找访问。但是不利于增、删。
 链表:   链表的地址空间是不连续的,对于内存空间不会造成浪费。便于大量元素的指定位置增、删。但查找速度相对较慢。 
 
二者特性刚好互补。)

2.从尾到头打印单链表 

//递归解决

void printfromback(ListNode* mylist){//1没有节点或者只有一个节点//2有多个节点if(mylist != NULL){return ;}else{printfromback(mylist->next);printf("%d ",mylist->data);}}

3.删除一个无头单链表的非尾节点 

//无头链表删除//后一个节点覆盖前一个节点 在释放后一个节点void deletnoheadlist(ListNode** pos ){ListNode* next;assert(*pos);assert((*pos)->next);next = (*pos)->next;(*pos)->data = next->data;(*pos)->next = next->next ;free(next);}
4.在无头单链表的一个节点前插入一个节点 

//无头链表插入//在pos后面插入一个数,再交换两个节点的内容void insertonheadlist(ListNode** pos, DataType input){int tmp;ListNode* cur = *pos;ListNode* NewNode = BuyNode(input);//插入新节点NewNode->next = (*pos)->next;(*pos)->next  = NewNode;//交换datatmp = NewNode->data ;NewNode->data = cur->data;(*pos)->data = tmp;}
5.单链表实现约瑟夫环 

//约瑟夫环//1把链表连起来ListNode* JosephRing(ListNode** ppList, int k){//1空链表//2非空ListNode* cur = *ppList;if(*ppList == NULL){return ;}while(cur->next != NULL){cur = cur->next;}cur->next = (*ppList);while((*ppList)->next != *ppList){int loop = k;while(--loop){(*ppList) = (*ppList)->next;}//删除(*ppList)->data = (*ppList)->next->data;(*ppList)->next = (*ppList)->next->next;}return  *ppList;}
6.逆置/反转单链表 

//链表逆置  头插法//建一个新链表    在新链表上头插原来的节点元素ListNode* ReverseList(ListNode** ppList){//1链表为空 或者只有一个元素//2链表不为空ListNode* cur = *ppList;ListNode* newlist=NULL ;if((*ppList)->next == NULL || *ppList == NULL){return ;}else{ListNode* tmp;while(cur != NULL){//摘节点tmp = cur;cur = cur->next;//放节点tmp->next =newlist;newlist = tmp;}return newlist;}}

7.单链表排序(冒泡排序&快速排序) 
//冒泡排序链表void bubble_sotr_list(ListNode* pList){//1链表为空或者只有一个节点//2有多个节点ListNode* cur = pList;ListNode* nextnode = cur->next;ListNode* stop = NULL;    DataType tmp;if((pList) == NULL || nextnode == NULL){return ;}else{while(stop != (pList)->next){cur = pList;nextnode = cur->next;while(nextnode != stop){ if((cur->data) > (nextnode->data)) {tmp = cur->data;cur->data = nextnode->data;nextnode->data = tmp; }cur =cur->next;nextnode = nextnode->next;}stop = cur;}}}

8.合并两个有序链表,合并后依然有序

//合并两个有序链表,合并后依然有序ListNode* MergeList(ListNode* List1,ListNode* List2){//1两个链表都为空//2其中一个链表为空//3两个链表都不为空ListNode* Newlist = NULL;ListNode* Newlisthead = NULL;if(List1 == NULL  && List2 == NULL){return NULL;}else if (List1 != NULL  && List2 == NULL){return List1;}else if (List1 == NULL  && List2 != NULL){return List2;}else{//摘链表头if(List1->data < List2->data){Newlist = List1;List1 = List1->next;}else{Newlist = List2;List2 = List2->next;}Newlisthead = Newlist;    //往节点后面加节点while(List1 !=NULL && List2 != NULL){if(List1->data < List2->data){Newlist->next = List1;Newlist = Newlist->next;        List1 = List1->next;}else{Newlist->next = List2;Newlist = Newlist->next;        List2 = List2->next;}    }//把剩余的链表链接上if(List1 == NULL){  Newlist->next = List2;}if(List2 == NULL){  Newlist->next = List1;}    return Newlisthead;}}

9.查找单链表的中间节点,要求只能遍历一次链表 

//查找链表中心元素 (只能遍历一次)//快慢指针ListNode* find_list_mid(ListNode* pList){//1为空//2只有一个或者两个节点//3有多个节点ListNode* slow = pList;ListNode* fast = pList;if(pList == NULL){return NULL ;}else if(pList->next == NULL || pList->next->next == NULL){return pList;}else{   while(fast && fast->next !=  NULL) //奇数偶数节点问题   {slow = slow->next;fast = fast->next->next;   }   return slow;}}

10.查找单链表的倒数第k个节点,要求只能遍历一次链表 

//找倒数第k个元素ListNode* find_tail_k(ListNode* pList,int k){//1链表为空        //2链表元素少于k//3链表元素多余kListNode* slow = pList;ListNode* fast = pList;if(pList == NULL){return NULL;}while(--k)    //先走k步                {fast = fast->next;if(fast == NULL){return NULL ;}}while(fast->next != NULL)   //一起走{    slow = slow->next;    fast = fast->next;}return slow;}