栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

链表的插入排序 Linked List Insertion Sort

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

链表的插入排序 Linked List Insertion Sort

一、插入排序 Insertion sort

 插入排序很像玩扑克牌中整理手牌的过程,从第二个数开始依次比较其与前面所用数据的大小,直到找到其需要在的位置。当从第二个数据遍历到最后一个数据之后就完成了整个数组的排序。

void InsertionSort(int arr[], int n)
{
    for(int i = 0; i= 0; j--)
        {
            //将比temp大的数依次向后移动一位
            arr[j+1] = arr[j];
        }
        //将temp插入到其正确的位置中
        arr[j+1] = temp;
    }
}
二、链表的插入排序

对于单向链表只能从前向后遍历,故从头节点遍历寻找未排好序的节点,如果是数组的话便只需向前遍历找到其正确的位置便可,但由于单向链表无法向前遍历只能重新从头遍历直到找到其正确位置。

同时为防止下次排序时需要从头遍历寻找未排好序的节点,可用precurrent指针储存已排好序的最后一节点,用temp指针储存需要移动的节点。

并且未防止节点需要插入头节点之前而产生边界问题进行讨论,则可以创建一个新的节点作为一个虚假的头节点并用prehead指向此节点。这样便将插入头节点之前变成了在两节点之间插入节点。

第一遍代码:但有错误,需要更改。

Node* InsertionSort(Node *head)
{
    //如果链表长度为0或1,不需要排序。
    if(head == NULL || head->nextptr == NULL )
    {
        return head;
    }
    //创建一个移动的指针遍历链表
    Node *current = head ;
    //创建一个虚假的头节点,将问题归一化处理
    Node *fakehead = new Node ;
    fakehead->Number = "0";
    fakehead->nextptr = head ;
    //创建一个节点来储存current前一节点
    Node *precurrent = fakehead ;
    //创建一个临时指针指向未排好序的节点
    Node *temp = NULL ;
    //从头节点遍历链表寻找到第一个未排好序的节点
    while (current->nextptr != NULL)
    {
        //时刻保持precurrent指向current指向的前一个节点
        if(precurrent->Number <= current->Number)
        {
            precurrent = current ;
            current = current->nextptr ;
        }
        else
        {
              
            temp = precurrent ;//错误,储存了要移动节点的前一节点
            
            //从链表中移出temp指针指向的节点
            precurrent->nextptr = current->nextptr ;
            //使用current指针遍历已排序的链表寻找temp指针指向节点的正确位置
            current = fakehead ;
            

            while (temp->Number <= current->nextptr->Number)//错误
            //排列的升降序未注意

            {
                current = current->nextptr ;
            }

            //将temp指向的节点插入current指向节点之后
            temp->nextptr = current->nextptr ;
            current->nextptr = temp ;
            //将current指针重新指向precurrent指针指向的节点的下一个节点
            current = precurrent->nextptr ;
        }
    }
    head = fakehead->nextptr ;
    delete fakehead ;
    return head;
}

Leetcode的代码题解:

ListNode* insertionSortList(ListNode* head) {
        if (head == nullptr) {
            return head;
        }
        ListNode* dummyHead = new ListNode(0);
        dummyHead->next = head;
        ListNode* lastSorted = head;
        ListNode* curr = head->next;
        while (curr != nullptr) {
            if (lastSorted->val <= curr->val) {
                lastSorted = lastSorted->next;
            } else {
                ListNode *prev = dummyHead;
                while (prev->next->val <= curr->val) {
                    prev = prev->next;
                }
                lastSorted->next = curr->next;
                curr->next = prev->next;
                prev->next = curr;
            }
            curr = lastSorted->next;
        }
        return dummyHead->next;
    }

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/insertion-sort-list/solution/dui-lian-biao-jin-xing-cha-ru-pai-xu-by-leetcode-s/
来源:力扣(LeetCode)

还在改进中…………敬请期待


改进后:

Node* InsertionSort(Node *head)
{
    //如果链表长度为0或1,不需要排序。
    if(head == NULL || head->nextptr == NULL )
    {
        return head;
    }
    //创建一个移动的指针遍历链表
    Node *current = head ;
    //创建一个虚假的头节点,将问题归一化处理
    Node *fakehead = new Node ;
    fakehead->Number = "0";
    fakehead->nextptr = head ;
    //创建一个节点来储存current前一节点
    Node *precurrent = fakehead ;
    //创建一个临时指针指向未排好序的节点
    Node *temp = NULL ;
    //从头节点遍历链表寻找到第一个未排好序的节点
    while (current->nextptr != NULL)
    {
        //时刻保持precurrent指向current指向的前一个节点
        if(precurrent->Number <= current->Number)
        {
            precurrent = current ;
            current = current->nextptr ;
        }
        else
        {

            //不应是temp = precurrent 否则将储存要移动节点的前一节点
            temp = current ;

            //从链表中移出temp指针指向的节点
            precurrent->nextptr = current->nextptr ;
            //暂时使用current指针遍历已排好序的链表寻找temp指针指向节点应该在的位置
            current = fakehead ;
            

            while (temp->Number >= current->nextptr->Number)
            

            {
                current = current->nextptr ;
            }

            //将temp指向的节点插入current指向节点之后
            temp->nextptr = current->nextptr ;
            current->nextptr = temp ;
            //将current指针重新指向precurrent指针指向的节点的下一个节点
            current = precurrent->nextptr ;
        }
    }
    head = fakehead->nextptr ;
    delete fakehead ;
    return head;
}

注:需时刻注意指针指向的位置!!!应该画个图分析!!!

全部代码如下:

#include 

using namespace std;

struct Node
{
    string Name;
    long long Number;
    string Sex;
    int age;
    Node* nextptr;
};

void BuildList(Node *head, int n);
void PrintList(Node *print);
void DeleteList(Node *current);
Node* InsertionSort(Node *current);

int main()
{
    Node *head = new Node;
    head->nextptr = NULL;
    BuildList(head, 10);
    cout << "Before ordering(id|age|name|sex)" << endl ;
    PrintList(head);
    head = InsertionSort(head);
    cout << "After ordering(id|age|name|sex)" << endl ;
    PrintList(head);
    DeleteList(head);
    return 0;
}

void BuildList(Node *head, int n)
{
    Node *current = head;
    for(int i=0; i> current->Name >> current->Number 
            >> current->Sex >> current->age;
        //创建一个新节点
        current->nextptr = new Node;
        current = current->nextptr;
        current->nextptr = NULL;
    }
}

void PrintList(Node *print)
{
    while(print->nextptr != NULL)
    {
        cout << "(" << print->Number << "|" << print->age 
             << "|" << print->Name << "|" << print->Sex << ")" << endl;
        print = print->nextptr ;
    }
}

void DeleteList(Node *current)
{
    Node *temp = NULL;
    //遍历链表删除节点
    while(current != NULL)
    {
        temp = current;
        current = current->nextptr;
        delete temp;
    }
}

Node* InsertionSort(Node *head)
{
    //如果链表长度为0或1,不需要排序。
    if(head == NULL || head->nextptr == NULL )
    {
        return head;
    }
    //创建一个移动的指针遍历链表
    Node *current = head ;
    //创建一个虚假的头节点,将问题归一化处理
    Node *fakehead = new Node ;
    fakehead->Number = 0;
    fakehead->nextptr = head ;
    //创建一个节点来储存current前一节点
    Node *precurrent = fakehead ;
    //创建一个临时指针指向未排好序的节点
    Node *temp = NULL ;
    //从头节点遍历链表寻找到第一个未排好序的节点
    while (current->nextptr != NULL)
    {
        //时刻保持precurrent指向current指向的前一个节点
        if(precurrent->Number <= current->Number)
        {
            precurrent = current ;
            current = current->nextptr ;
        }
        else
        {

            //不应是temp = precurrent 否则将储存要移动节点的前一节点
            temp = current ;

            //从链表中移出temp指针指向的节点
            precurrent->nextptr = current->nextptr ;
            //暂时使用current指针遍历已排好序的链表寻找temp指针指向节点应该在的位置
            current = fakehead ;
            

            while (temp->Number >= current->nextptr->Number)
            

            {
                current = current->nextptr ;
            }

            //将temp指向的节点插入current指向节点之后
            temp->nextptr = current->nextptr ;
            current->nextptr = temp ;
            //将current指针重新指向precurrent指针指向的节点的下一个节点
            current = precurrent->nextptr ;
        }
    }
    head = fakehead->nextptr ;
    delete fakehead ;
    return head;
}

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/643733.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号