【C++】链表实现的各种情况(含面试题)

来源:互联网 发布:股票评测软件 编辑:程序博客网 时间:2024/06/05 18:06

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

答:顺序表在空间上是连续的,并支持随机访问,用下标会很方便。在不增容的情况下,尾插的效率很高,但其他情况就不是很乐观。顺序表的高速缓存的利用率比链表高。而链表的头插以及中间插入的效率要比顺序表的效率要高,链表若需要增容会比顺序表要方便的多。

以下代码下面的题目的通用:

#include<stdio.h>#include<stdlib.h>#include<assert.h>typedef int DataType;typedef struct Node{    DataType data;    struct Node* next;}Node;void PushBack(Node** ppHead,DataType x);void PrintList(Node* pHead);void TailToHead(Node* pHead);void NoneHead(Node* pos);void Insert(Node* pos, DataType x);Node* Find(Node* pList, DataType x);Node* Josephus(Node* hus,int k);void Reverse(Node** ppHead);void SortList(Node* pHead);Node* MergeList(Node* list1, Node* list2);Node* FindMid(Node* pHead);Node* FindK_Node(Node* pHead,size_t k);
#include"test.h"//创建节点Node* BuyNode(DataType x){    Node* tmp = (Node*)malloc(sizeof(Node));    if (tmp != NULL)    {        tmp->data = x;        tmp->next = NULL;    }    return tmp;}Node* Find(Node* pList, DataType x){    assert(pList);    while (pList->next != NULL)    {        if (pList->data == x)        {            return pList;        }        pList = pList->next;    }    return pList;}//打印void PrintList(Node* pList){    assert(pList);    Node* Node = pList;    while (Node)    {        printf("%d ", Node->data);        Node = Node->next;    }    printf("\n");}//尾插void PushBack(Node** ppList, DataType x){        if (*ppList == NULL)        {            *ppList = BuyNode(x);        }        else        {            Node* list = *ppList;            while (list->next != NULL)            {                list = list->next;            }            list->next = BuyNode(x);        }}
//main函数#define _CRT_SECURE_NO_WARNINGS 1#include"List.h"int main(){    test1();    test2();    test3();    test4();    test5();    test6();    test7();    test8();    test9();    system("pause");    return 0;}

2.从尾到头打印一个单链表

//从尾到头打印一个单链表void PrintTailToHead(Node* List){    if (List == NULL)        return;    PrintTailToHead(List->next);    printf("%d ", List->data);}//测试void test1(){    Node* list = NULL;    PushBack(&list, 1);    PushBack(&list, 2);    PushBack(&list, 3);    PushBack(&list, 4);    PushBack(&list, 5);    PrintList(list);    PrintTailToHead(list);    printf("\n");}

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

//删除一个无头单链表的非尾节点void NoneHead(Node* pos){    assert(pos&&pos->next);    Node* next;    next = pos->next;    pos->data = next->data;    pos->next = next->next;    free(next);}void test2(){    Node* list = NULL;    PushBack(&list, 1);    PushBack(&list, 2);    PushBack(&list, 3);    PushBack(&list, 4);    PushBack(&list, 5);    PrintList(list);    Node* pos = list;    pos = pos->next;    NoneHead(pos);    PrintList(list);    printf("\n");}

4.在无头单链表的一个节点前插入一个节点

//在无头单链表的一个节点前插入一个节点void Insert(Node* pos,DataType x){    assert(pos);    Node* next = pos->next;    Node* tmp = BuyNode(pos->data);//新建一个pos位置的节点    pos->data = x;//把要插入的数赋给pos位置的data;    pos->next = tmp;    tmp->next = next;}void test3(){    Node* list = NULL;    PushBack(&list, 1);    PushBack(&list, 2);    PushBack(&list, 3);    PushBack(&list, 4);    PushBack(&list, 5);    PrintList(list);    Node* pos = list;    pos = pos->next;    Insert(pos,30);    PrintList(list);    printf("\n");}

5.单链表实现约瑟夫环

//单链表实现约瑟夫环Node* Josephus(Node* hus, int k){    assert(hus);    while (hus->next != hus)//当剩下的还有其他时就进去    {        int count = k;        while (--count)        {            hus = hus->next;//循环k-1次,直到数到k的那个人出现就停止这时,hus就是要删除的那个。        }        Node* next = hus->next;//以下三步分别是将后面的数据,next依次往前挪动        hus->data = next->data;        hus->next = next->next;        free(next);    }    return hus;}void test4(){    Node* tail;    Node* list = NULL;    PushBack(&list, 1);    PushBack(&list, 2);    PushBack(&list, 3);    PushBack(&list, 4);    PushBack(&list, 5);    PrintList(list);    tail = Find(list, 5);    tail->next = list;    printf("留下的是:%d\n", Josephus(list, 3)->data);    printf("\n");}

6.逆置/翻转单链表

void Reverse(Node** ppHead){    Node* n0, *n1, *n2;    if (*ppHead == NULL)    {        return;    }    n0 = NULL;    n1 = *ppHead;    n2 = n1->next;    while (n1 != NULL)    {        n1->next = n0;//逆置        //后移        n0 = n1;        n1 = n2;        if (n2)        n2 = n2->next;    }    *ppHead = n0;//把n0置为头}void test5(){    Node* list = NULL;    PushBack(&list, 1);    PushBack(&list, 2);    PushBack(&list, 3);    PushBack(&list, 4);    PushBack(&list, 5);    PrintList(list);    Reverse(&list);    PrintList(list);    printf("\n");}

7.单链表排序

//单链表排序void SortList(Node* pHead){    Node* tail=NULL;    if (pHead == NULL || pHead->next == NULL)    {        return;    }    Node* cur = pHead, *next = cur->next;    while (next != NULL)    {    //若前一个数据大于后一个数据则交换两个数据        if (cur->data > next->data)        {            DataType tmp = cur->data;            cur->data = next->data;            next->data = tmp;        }        cur = cur->next;//当前的指针指向下一个        next = next->next;//下一个指针指向下下一个    }    tail= cur;//当没有两个可以比较的数据时,将最后一个数据直接赋上}void test6(){    Node* list = NULL;    PushBack(&list, 1);    PushBack(&list, 2);    PushBack(&list, 8);    PushBack(&list, 3);    PushBack(&list, 4);    PrintList(list);    SortList(list);    PrintList(list);}

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

//合并两个有序的链表,合并后依然有序Node* MergeList(Node* list1, Node* list2){    Node* list = NULL;    if (list1 == NULL)    {        return list2;    }    if (list2==NULL)        return list1;    if (list1->data > list2->data)    {        list = list2;        list2 = list2->next;    }    else    {        list = list1;        list1 = list->next;    }    Node* tail=list;    while (list1&&list2)    {        if (list1->data < list2->data)        {            tail->next = list1;            list1 = list1->next;        }        else        {            tail->next = list2;            list2 = list2->next;        }        tail = tail->next;    }    if (list1)        tail->next = list1;    if (list2)        tail->next = list2;    return list;}void test7(){    Node* list1 =NULL;    Node* list2=NULL;    PushBack(&list1, 1);    PushBack(&list1, 3);    PushBack(&list1, 5);    PushBack(&list1, 7);    PushBack(&list1, 9);    PrintList(list1);    PushBack(&list2, 0);    PushBack(&list2, 2);    PushBack(&list2, 4);    PushBack(&list2, 6);    PushBack(&list2, 8);    PrintList(list2);    Node* list=MergeList(list1, list2);    PrintList(list);}

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

//查找单链表的中间节点,要求只遍历链表一遍//定义快慢指针,快指针每次走两步,慢指针每次走一步Node* FindMid(Node* pHead){    Node* slow = pHead, *fast = pHead;    while (fast&&fast->next)    {        slow = slow->next;        fast = fast->next->next;    }    return slow;}void test8(){    Node* list = NULL;    PushBack(&list, 1);    PushBack(&list, 3);    PushBack(&list, 5);    PushBack(&list, 7);    PushBack(&list, 9);    PrintList(list);    printf("中间节点为:%d \n",FindMid(list)->data);}

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

//查找单链表的倒数第k个节点,要求只能遍历一遍链表Node* FindK_Node(Node* pHead,size_t k){    Node* slow = pHead, *fast = pHead;    while (--k)    {        if (fast == NULL)            return NULL;        fast = fast->next;    }        while (fast->next)        {            slow = slow->next;            fast = fast->next;        }    return slow;}void test9(){    Node* list = NULL;    PushBack(&list, 1);    PushBack(&list, 3);    PushBack(&list, 5);    PushBack(&list, 7);    PushBack(&list, 9);    PrintList(list);    printf("中间节点为:%d \n", FindK_Node(list,2)->data);}
原创粉丝点击