链表的常用算法c++

结点定义:struct node
创建无序链表:Create()
遍历链表:Print() Search()
删除结点:Delete_one_node()
释放链表:Delete_chain()
插入一个结点:Insert()
创建有序链表:Create_sort()

#include <iostream>
#include<iomanip>
using namespace std;

/*不带头节点*/

//定义链表结点结构
struct node{
    int data;
    node *next;
};

//动态创建无序链表,函数返回值为链表的首指针;程序运行时,依次输入链表中各结点的数据,以输入'-1'表示结束。
node * Create(){
    node *p1, *p2 = NULL, *head;//p1指向新开辟的结点,p2指向建立过程中的链表尾结点,head指向链表首结点
    int a;
    head = NULL;//初始时,设置head为空指针

    cout << "正在创建一条无序链表...\n";
    cout << "请输入一个正整数,以-1结束:";
    cin >> a;//输入第一个数据

    while(a != -1){
        p1 = new node;//动态申请一个新结点 <指针变量> = new <数据类型> 程序结束前必须通过delete释放
        p1->data = a;//给新结点数据域赋值

        if(head == NULL)//只有第一次加入结点时本条件成立
            head = p2 = p1;//加入首结点
        else{
            p2->next = p1;//连入中间结点
            p2 = p1;
        }

         cout << "请输入一个正整数,以-1结束:";
         cin >> a;//输入下一个数据

    }

    if(head != NULL){//如建立的不是空链表,则需要进行尾结点处理

        p2->next = NULL;
    }

    return head;//返回链表首指针
}


//遍历链表:输出链表中各结点数据值

void Print(const node *head){//常量指针,即指向常量的指针,目的是保护指针所指向的结点值不被改变
    const node *p;//p是指向常量的指针

    p = head;
    cout << "链表中各节点数据为:";

    while(p != NULL){
        cout << setw(4) << p->data;

        p = p->next;
    }
    cout << endl;


}

//遍历链表:在链表中顺序查找某结点的值,如果存在则返回该结点的指针,否则返回空指针

const node * Search(const node *head, int x){//函数的返回值依然是指向常量的指针,目的是在调用Search()的主函数中保护查找到的节点
    const node *p;//p是指向常量的指针

    p = head;
    while(p != NULL){

        if(p->data == x)
           return p;//若找到,则返回该节点的指针
        p = p->next;
    }
    return NULL;//若找不到,则返回空指针
}


//删除结点:删除链表中结点的data为num的结点,为简单起见,若有多个,则只删除第一个
/*算法整体思路:首先查找待删除的结点(由p1指向),若找到则删除它,若未找到则无需删除:
1)若待删除的结点是首结点,此时需要重新设置首指针 2)若待删除的结点是其他结点,则不需要修改首指针*/
node *Delete_one_node(node *head, int num){
    node *p1, *p2 = NULL;//指针p1向下一结点方向(尾结点方向)依次查找待删除的结点,p2始终指向p1的前一个结点

    if(head == NULL){//判断链表是否为空

        cout << "链表为空,无结点可删除!\n";
        return NULL;
    }

    p1 = head;
    while(p1->data != num && p1->next != NULL){//循环查找待删除结点,未找到且链表未遍历完,则继续循环

        p2 = p1;//p2记住p1
        p1 = p1->next;//p1指向后一个结点,p2指向的结点在p1指向的结点之前

    }

    if(p1->data == num){//找到了待删结点,由p1指向

        if(p1 == head)//找到的是首结点
            head = p1->next;//重新设置head的指向
        else//找到的不是首结点
            p2 = p1->next;//不管是中间结点还是尾结点,都只需要将p2的next指针绕过p1结点指向p1的下一个结点即可

        delete p1;//无论找到的结点是否为首结点,结点本身的空间是要释放的
        cout << "删除了一个结点!\n";

    }
    else//未找到待删除结点
        cout << num << " 链表上没有找到待删除的结点!\n";

    return head;

}

//插入一个结点(对于升序链表),插入结点时,若原链表是空链表,则构造一个具有一个结点的链表,首结点指向该结点即可
//若原链表是非空的:1)插入在原链表首结点之前 2)插入在链表中间 3)插入在链表尾结点之后
node *Insert(node *head, node *p){
    node *p1, *p2 = NULL;//p2为p1的前一个结点,p1代表当前在处理的结点

    if(head == NULL){//原链表为空链表

        head = p;
        p->next = NULL;

        return head;
    }

    p1 = head;

    while((p->data) > (p1->data) && p1->next != NULL){//寻找待插入节点的位置,直到找到或链表已经遍历完

        p2 = p1;//p2记住p1
        p1 = p1->next;//p1指向后一个结点,p2指向的结点在p1指向的结点之前

    }

    if((p->data) <= (p1->data)){//插入在p1之前

        p->next = p1;//但p1有可能是首结点,所以需要进一步判断

        if(head == p1) head = p;//插在链表首部

        else p2->next = p;//插在链表中间
    }
    else{//插在链表末尾

        p1->next = p;
        p->next = NULL;

    }

    return head;

}

//创建有序链表,基于Insert()方法->升序:
//循环输入数值,建立一个新结点,其数据域的值就是输入的数值,调用插入结点函数Insert(),
//将该新结点插入到链表中,使链表始终保持升序
node *Create_sort(){
    node *p, *head = NULL;
    int a;
    cout << "正在创建建一条有序链表...\n";
    cout << "请输入一个整数,以-1结束:";
    cin >> a;//输入第一个结点的值

    while(a != -1){//当输入-1时结束创建过程
            
        p = new node;//创建一个新结点,p指向它
        p->data = a;
        head = Insert(head, p);//将p结点插入head链表,保持升序
        cout << "请输入一个整数,以-1结束:";
        cin >> a;//输入下一结点的值

    }
    return head;//返回升序链表首指针
}


//释放链表:释放链表所有结点的空间
void Delete_chain(node * head){
    node *p;
    while(head){//等价于 head != NULL
        p = head;
        head = head->next;
        delete p;//delete <指针变量> :释放一个由<指针变量>指向的变量的空间

    }

    cout << "释放了链表" << endl;

}



int main()//测试以上所有函数
{
    node * head;
    int num;
    head = Create();
    Print(head);

    cout << "请输入待删除结点上的整数:";
    cin >> num;
    head = Delete_one_node(head, num);//此函数返回node类型的指针,即头结点的指针
    Print(head);

    cout << "请输入要查找的整数:";
    cin >> num;
    if(Search(head, num) != NULL)
        cout << num << " 在链表中\n";
    else
        cout << num << " 不在链表中\n";
    Delete_chain(head);//一定要在测试函数末尾释放链表,否则后果不可预测

    head = Create_sort();//创建有序链表
    Print(head);
    Delete_chain(head);//一定要在测试函数末尾释放链表,否则后果不可预测

    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值