关于单链表有哪些有趣的问题

在补习班上课2个多月了.今天上课老师讲了单链表的很多操作.由于之前一直是自学状态,涉猎单链表方面很少.所以听完感觉之前学习的真的是太少了,还需要好好努力去扩充自己的知识储备.

多题预警,与君共勉~~

首先说一下单链表的结构吧,链表分为数据域和指针域.指针域存放的是下一个结构体的指针.

也可以设置一个带有控制信息的链表,控制信息的链表除了含有普通的数据域和指针域除外,还含有一个另外的结构体,这个另外的结构题存储的是头尾节点的信息,以及链表的长度.

基础的链表增删查就不多罗嗦了,

在给出答案之前,先把问题给大家.先思考在查询答案对思维是一种锻炼哦~~

1.如何给一个链表排序?  

2.合并两个链表,并且让合并后的链表有序

3.找到链表的倒数第n个节点并返回

4.链表翻转

5.判断两个链表是否有相交

6.给出一个链表,删除这个链表中给出的节点(你能想到用最短的时间的方法)   注:链表给出,删除的节点给出,如何去删除它

7找到环的交点.


如果没见过这几道题就先思考一下^_^




















如何排序?(选择一个排序方法并使用库函数memcpy)

合并(创建一个新链,用排序模块)

找位置(用两个指针,一个跑n次,另一个在开始跑)

翻转(尾部删除.头部插入)

相交(两个指针分别指向不同的链表.同时跑,如果两个的next都为空的时候两个节点相同.说明相交)

删除(找到节点的next让两个节点的数据域交换,然后删除它的next)

交点(先让一个指针的速度是另一个的两倍,找到交点,然后让一个指针在交点跑,另一个在初始位置跑.相同的位置则说明相交点)



求交点得需要一个简单的证明:

首先定义一些长度一会证明,环的长度设为m

头到相遇的节点的长度为x

两个指针一个跑得速度是另一个的两倍

相遇慢指针走的长度设为z

那么快指针走的是2z

慢指针在圆上跑了y个单位.

z == x+y

2z - z == km(k = 1,2,3,...)(两者相遇的时候肯定一个在环里跑了k圈,而另一个还没到一圈)

现在让一个节点指向头,另一个指向相交节点,两者同时跑一个单位,如果走x个单位,那么一个指针在交点处,而另一个指针呢?

它也走了x个单位,但是换算一下  x == z-y

z == km 所以x == km-y是多少呢

正好走到了交点处!!!

废话不说,直接撸代码

我先把我的结构题和一些宏定义贴上来,

注:其中一些函数引用了Malloc,swap,pop,push等模块,可以当作伪代码来看,下一篇会帖出完整代码,亲测可运行

注:pop_back 尾部弹出,pop_front头部弹出,push_front头插,push_back尾插,Malloc分配内存(其实就是用的malloc)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRUE     (1)
#define FALSE    (0)
#define ZERO     (0)
#define ONLY_ONE (1)
typedef unsigned char Boolean;//c语言里没有bool类型所以定义一个
//控制信息
typedef struct list{
    struct node *head;
    struct node *tail;
    int         count;
}*List;
//节点信息
typedef struct node{
    int          data;
    struct node *next;
}*p_node;


1:

void      sort_list_descent(List *list)               //降序排列
{
    List_node *p_node = NULL;
    List_node *q_node = NULL;
    unsigned long data_size = 0;

    if(list == NULL || list->count < TWO){
        return ;
    }
 // List_node *p = list->head;

 // p->next = NULL;

 // ((unsigned long)&(((List_node *)0)->next))

 // sizeof(List_node) - sizeof(List_node *);
 
   
    // int               data;  // 0   1   2   3
    //                          // 4   5   6   7
    // struct List_Node *next;  // 8   9  10  11
    //                            12  13  14  15
    //

    data_size = get_data_size();    //求得数据区域得大小
    for(p_node = list->head; p_node->next; p_node = p_node->next){
        for(q_node = p_node->next; q_node ; q_node = q_node->next){
            if(p_node->data < q_node->data){ 
                swap(p_node, q_node, data_size); //交换函数               
            }
        }
    }
}




2:
List      *merge_two_lists(List *list1, List *list2)    //合并两个有序链表
{
    List *result = NULL;
    List_node *list1_move = NULL;   
    List_node *list2_move = NULL;
    if(list1 == NULL || list2 == NULL){
        return result;
    }

    result = init_list();   //结果链表得初始化

    list1_move = list1->head;
    list2_move = list2->head;

    //      | head |              tail | count |
    //          \                 /       n-> n - 1
    //           \               /
    //            node1->node2->node3
    //
    //
    //      | head |              tail | count |
    //          \                 /       n-> n - 1
    //           \               /
    //            node1->node2->node3
    //


    //如果两个链表都没有遍历完,进行比较
    while(list1_move != NULL && list2_move != NULL){
        if(list1_move->data <= list2_move->data){
            push_back(result, list1_move->data);
            list1_move = list1_move->next;
        }else{
            push_back(result, list2_move->data);
            list2_move = list2_move->next;
        }
    }

    //当两个链表中任何一个遍历结束,则把另外一个进行尾部添加
    while(list2_move != NULL){
        push_back(result, list2_move->data);
        list2_move = list2_move->next;
    }

    while(list1_move != NULL){
        push_back(result, list1_move->data);
        list1_move = list1_move->next;
    }

    return result;
}





3:p_node find_revise_node(List list,int num)
{
    p_node p = list->head;
    p_node q = list->head;
    if(list == NULL || num == 0){
        return NULL;
    }
    while(num--){
        p = p->next;
    }
    while(p){
        q = q->next;
        p = p->next;
    }
    return q;
}




4.<pre name="code" class="cpp">List reverse_list1(List list)//逆置链表
{
    p_node p = list->head;
    if(list == NULL || list->count < 2)
    {
        return NULL;
    }
    List L;
    L = init_list();
    while(p){
        push_front(L,p->data);
        p = p->next;
    }
    return L;
}






5:


Boolean is_list_intersect(List list1,List list2)//判断链表是否相交
{
    if(list1 == NULL || list2 == NULL)
        return FALSE;
    return list1->tail == list2->tail;
}


6

void delete_one_node(List list,int value)//O(1)时间复杂度删除节点
{
    p_node p = list->head->next;
    if(list == NULL){
        return ;
    }
    while(p->data != value && p){
        p = p->next;
    }
    if(p != list->tail){
        p->data = p->next->data;
        p->next = p->next->next;
    }
    else
        pop_back(list);
    list->count--;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值