链表的总结(链表排序、翻转、删除节点)

简要说下思路:

node* sort_linklist(node *head){//链表排序(类比选择排序)
    node *sortedarray,*previous,*temp;
    for (int i=1; i<=n; i++) {
        sortedarray=creatnode();
        sortedarray->data=selectmm_linklist(head);
        if (i==1) {
            temp=previous=sortedarray;
        }
        else{
            previous->next=sortedarray;
        }
        delete_linklist(head, sortedarray->data);//delete会自动删除链表中元素至链表中元素个数为0,就退出while循环
        previous=sortedarray;
    }
    return temp;
}

1.链表排序(代码如上)

我采用的排序方法是直接用类似于数据结构中的选择排序的方法,首先找出优先级最大的数字,在我的代码里面最小的数字具有最大的优先级,需要注意的是:选择排序为了进行多次扫描,必须要把那个最小的元素从链表中删除,因为它并不等同于数组(数组的话能直接把最小的那个元素直接放在最前的位置,但是链表如果这样操作的话就太麻烦了),每次我们取出的那一个数我们就把它直接放入新的链表里面,只需要放在最后的位置就行了,因为我们每次取的数字都优先级一次比一次小(比如3,2,1变成1,2,3),当排序成功了,新的链表的节点个数就为n了,而之前的链表为空了,因为之前链表里面的值都转到了新的排好序的链表了.


node* reverse_linklist(node *head){//from a->b->c to a<-b<-c,3个指针(current,head,previous)实现链表翻转
    node *previous=NULL,*current=head;
    while (1) {//在循环里面的话head其实代表的是后继指针
        head=head->next;//这句话肯定没次都要执行
        current->next=previous;//修改current指针
        previous=current;
        if (!head) {
            return current;
        }
        current=head;//头指针变为current
    }
}


2.链表翻转(代码如上)

链表翻转的话,我觉得容易出错的地方就是指针的记录吧,注意一下链表的特性,链表具有递进的结构,a->b->c->d->null,翻转后它变为null-<a-<b-<c-<d,我们肯定要从头开始翻转,但是如果我们直接修改a的next指针的话整个链表就丢失了(我一直觉得头指针是一个链表最重要的部分,没有头指针,链表就丢了,就想没有思想没有头脑的人找不到自己的归属),所以我们需要通过另外一个指针来存b->c->d->null这部分,存完以后就可以执行循环了,注意终止条件是head=null,因为head=null的时候current正好在最后一个元素,此时最后一个元素就是头指针了,返回current就可以直接通过current访问翻转后的链表了.


3.下面直接贴一下所有的代码吧,里面有详细的实现算法的过程.

#include "iostream"
#include "cstdlib"
using namespace std;
struct node{
    int data;
    node *next;
};
node *head;int n;
node *creatnode(){//创建节点
    node *e;
    e=(node*)malloc(sizeof(node));
    e->next=NULL;
    return e;
}
void init(node *&head){//初始化链表,*&表示对指针的引用,注意一下引用在函数体返回的时候head值会改变,类比swap中的引用
    node *previous,*current;
    previous=current=NULL;
    int a;
    cin>>n;
    for (int i=1; i<=n; i++) {
        cin>>a;
        current=creatnode();
        current->data=a;
        if (i==1) {
            head=current;
        }
        else{
            previous->next=current;
        }
        previous=current;
    }
}
void get_linklist(node *head){//输出链表所有元素
    while (head) {
        cout<<head->data<<' ';
        head=head->next;
    }
    cout<<endl;
}
node* reverse_linklist(node *head){//from a->b->c to a<-b<-c,3个指针(current,head,previous)实现链表翻转
    node *previous=NULL,*current=head;
    while (1) {//在循环里面的话head其实代表的是后继指针
        head=head->next;//这句话肯定没次都要执行
        current->next=previous;//修改current指针
        previous=current;
        if (!head) {
            return current;
        }
        current=head;//头指针变为current
    }
}
void delete_linklist(node *&head,int val){//删除链表中某个节点
    node *previous,*temp;
    temp=head;
    if (head->data==val) {
        head=head->next;
    }
    else{
        while (temp) {
            if (temp->data==val) {
                previous->next=temp->next;
                break;
            }
            previous=temp;
            temp=temp->next;
        }
    }
}
int selectmm_linklist(node *head){
    int min=1000000;
    while (head) {
        if (head->data<min) {
            min=head->data;
        }
        head=head->next;
    }
    return min;
}
node* sort_linklist(node *head){//链表排序(等同于选择排序)
    node *sortedarray,*previous,*temp;
    for (int i=1; i<=n; i++) {
        sortedarray=creatnode();
        sortedarray->data=selectmm_linklist(head);
        if (i==1) {
            temp=previous=sortedarray;
        }
        else{
            previous->next=sortedarray;
        }
        delete_linklist(head, sortedarray->data);//delete会自动删除链表中元素至链表中元素个数为0,就退出while循环
        previous=sortedarray;
    }
    return temp;
}
int main(){
    init(head);
    get_linklist(head);
    get_linklist(reverse_linklist(head));
    head=sort_linklist(head);
//    delete_linklist(head, 1);
    get_linklist(head);
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值