148. 排序链表

本文介绍了一种基于归并排序算法的链表排序方法,该算法具备O(nlogn)的时间复杂度和O(1)的空间复杂度。通过在原链表上直接操作进行合并,以及在拆分过程中使用头节点进行n-1步操作,实现了高效的排序过程。文章详细解析了split和merge函数的实现细节。

nlog 的算法,是归并排序,同时是o1的空间复杂度,所以在merge的时候,直接在原链表上进行操作。在split的时候,由于包含head, 所以是走n-1步。

class Solution {

public:

    ListNode* merge(ListNode* l1, ListNode* l2){

            ListNode dummyhead(0);

            auto p = &dummyhead;

            while(l1 && l2){

                if(l1->val < l2->val){

                    p->next = l1;

                    p = l1;

                    l1 = l1->next;

                }

                else{

                    p->next = l2;

                    p = l2;

                    l2 = l2->next; 

                }

            }

            p->next = l1 ? l1 : l2;

            return dummyhead.next;

    }

    

    ListNode* split(ListNode* head, int n){

            ListNode* split = new ListNode(0);

            for(int i = 0; i < n-1 && head; i++){

                head = head->next;

            }

            //while(--n && head) head = head->next;

            if(!head) return NULL;

            split = head->next;

            head->next= NULL;

            return split;

    }

    

    ListNode* sortList(ListNode* head) {

            for(int i = 0; i < 2 && head; i++){

                cout << "i is:" << i << endl;

            }

            ListNode* dummyHead = new ListNode(0);

            dummyHead->next = head;

            ListNode* left = head; ListNode* right = head;

            ListNode* current = head;

            ListNode* p = head;

            int length(0);

            while(p) {length++; p=p->next;}

            //cout << length;

            for(int step = 1; step < length; step *= 2){

                //cout << "step" << step << endl;

                auto tail = dummyHead; 

                current = tail->next;

                while(current){

                    left = current;

                    right = split(left, step);

                    //cout << "right val" << right->val << endl;

                    current = split(right, step);

                    tail->next = merge(left, right);

                    while(tail->next) tail = tail->next;

                }

            }

        return dummyHead->next;

    }

};

先展示下效果 https://pan.quark.cn/s/c5feb84a447a 在微机原理与接口技术的知识体系中,ROM(只读存储器)与RAM(随机存取存储器)的地址是极为重要的概念。 它们构成了计算机硬件系统中的核心构成部分,承担着存储程序和数据的任务。 本习题集主要聚焦于探讨ROM/RAM的地址区间、138译码器在RAM地址划分中的应用情况,以及计算机字长对于寻址能力的制约作用。 ROM和RAM的地址区间是根据微处理器的设计方案来界定的。 可寻址的存储单元总数取决于地址线的数目。 举例来说,一条16位的地址线能够指向2^16个单元,即64KB。 ROM通常用于存储初始化指令和固定不变的数据,其地址空间一般设置在内存的较高区域。 相对而言,RAM则用于临时存储正在运行的程序和数据,通常位于较低的地址区间。 深入理解这些地址区间有助于我们进行系统存储布局的设计与分析。 138译码器是一种常用的地址解析装置,经常用于指定RAM的物理地址。 138译码器拥有三个输入地址端口和八个输出端口,当输入地址端口呈现特定组合状态时,相应的输出端口会被激活,进而选定特定的RAM芯片。 例如,在一个基础系统中,倘若配置两个138译码器,便可以为8片4KB的RAM芯片分配互不重叠的地址。 借助解码机制,我们能够灵活地配置和扩充系统的内存资源。 再者,计算机的字长对其寻址区间具有直接影响。 字长表征了计算机单次能够处理的数据宽度,常见的规格有8位、16位、32位和64位等。 针对一个n位的计算机,其最大直接寻址的内存容量为2^n字节。 比如,一台32位计算机的最大寻址空间为2^32字节,即4GB。 字长的提升不仅代表着更宽广的寻址能力,同时也通常意味着更卓越的计算性能和更丰富的数据类型支持。 在本次习题集中,你可...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值