算法学习-链表-level1

这篇具有很好参考价值的文章主要介绍了算法学习-链表-level1。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

part1:单向链表

1、构造

struct Node* insertNode(node* head, node* nodeInsert, int position)
{
    if (head == NULL) {
        return nodeInsert;
    }

    int listSize = getLength(head);
    if (position < 1 || position > listSize + 1) {
        cout << "OVERREACH!" << endl;
    }

    if (position == 1) {
        nodeInsert->next = head;
        head = nodeInsert;
        return head;
    }

    node* prev = head;
    int cnt = 1;
    while (cnt < position - 1) {
        cnt++;
        prev = prev->next;
    }
    nodeInsert->next = prev->next;
    prev->next = nodeInsert;
    return head;
}

2、创建节点并初始化

struct Node* initList()
{
    node* head = NULL;
    node* curr = (node*)malloc(sizeof(node));
    curr->val = 0;
    curr->next = NULL;
    head = curr;
    for (int i = 1; i < 10; i++)
    {
        node* temp = (node *)malloc(sizeof(node));
        temp->val = i;
        temp->next = NULL;
        curr->next = temp;
        curr = curr->next;
    }
    return head;
}

3、基础操作-增删

首先写出打印函数方便后续的检验

void printList(node *head)
{
    for (node* temp = head; temp != NULL; temp = temp->next)
    {
        cout << temp->val << " ";
    }
    cout << endl;
    return;
}

接下来写出获取链表长度的函数,目的是检验接下来插入时的边界的的检验

int getLength(node *head)
{
    int length = 0;
    node *temp =  head;
    while (temp!=NULL)
    {
        length++;
        temp = temp->next;
    }
    return length;
}

准备工作结束~ 

那么接下来正式开始链表的增删操作

struct Node* insertNode(node* head, node* nodeInsert, int position)
{
    if (head == NULL) {
        return nodeInsert;
    }

    int listSize = getLength(head);
    if (position < 1 || position > listSize + 1) {
        cout << "OVERREACH!" << endl;
    }

    if (position == 1) {
        nodeInsert->next = head;
        head = nodeInsert;
        return head;
    }

    node* prev = head;
    int cnt = 1;
    while (cnt < position - 1) {
        cnt++;
        prev = prev->next;
    }
    nodeInsert->next = prev->next;
    prev->next = nodeInsert;
    return head;
}

这里的增加节点的操作需要注意的是对于每一种情况最好做到不重不漏 

链表为空、插入位置的不合法、首个插入以及在中间插入

注意:

1、对于中间插入,因为单向链表中存在“开弓没有回头箭”的情况 所以我们选择记录插入节点的前一个节点(prev)这样我们就可以利用prev->next的方法很好的去进行接下来的操作。

2、插入的过程需要遵守一个原则:先连接后续的节点,再连接前面的节点。否则在我们连接好前面的节点与插入节点之后,后续的节点就会全部丢失。

这里给出图解:

算法学习-链表-level1,算法,学习,链表

这里给出一个单调插入的思路:

先进行数字的寻找,这里我们用循环遍历数组,寻找到符合要求的smaller节点

    node* smaller = head;
    while ((smaller->next != NULL) && (smaller->next->val < nodeInsert->val)) {
        smaller = smaller->next;
    }

注意:

1、这里循环的条件顺序不可以改变,进行逻辑与操作时会先进行前键的判断,也就是先判断smaller节点的next是否存在,只有存在时才能进行其下一节点大小的比较。否则程序会直接崩溃

2、这也是写链表中很重要的点,只有先确定节点的存在性才能进行下面一系列的操作,比如双向链表的插入中操作curr->prev->next = curr->next,只有确认curr->next节点的存在才能进行进一步的比对。这也是链表操作实现中分类的前提,理解好这一步就可以理解如何分类进行链表的操作,例如:双向链表头插法时,只有头节点存在head->prev = curr才能实现,所以需要提前判断,每种情况都要有所思考,不重不漏。

接下来是单调插入的具体实现代码:

struct Node* monotonousInsertnode(node* head, node* nodeInsert)
{
    if (head == NULL) {
        return nodeInsert;
    }

    if (nodeInsert->val < head->val) {
        nodeInsert->next = head;
        head = nodeInsert;
        return head;
    }

    node* smaller = head;
    while ((smaller->next != NULL) && (smaller->next->val < nodeInsert->val)) {
        smaller = smaller->next;
    }
    nodeInsert->next = smaller->next;
    smaller->next = nodeInsert;
    return head;
}

删除部分与插入部分相似这里不做过多说明

直接上代码:

struct Node* deleteNode(node* head, int position)
{
    if (head == NULL) {
        return NULL;
    }

    int listSize = getLength(head);
    if (position < 1 || position > listSize) {
        cout << "INPUT ERROR" << endl;
        return head;
    }

    if (position == 1) {
        node* temp = head;
        head = head->next;
        free(temp);
        return head;
    }

    node* prev = head;
    int cnt = 1;
    while (cnt < position - 1) {
        cnt++;
        prev = prev->next;
    }
    node* curr = prev->next;
    prev->next = curr->next;
    free(curr);
    return head;
}

最后附带一些可能用的上的测试代码:

void testInsert()
{
    node* head = NULL;
    node* temp = (node*)malloc(sizeof(node));
    temp->val=1;
//    插入第一个元素
    head = insertNode(head,temp,1);
    printList(head);

 //    插入第二个元素,因为前面至于一个元素,这里就是在尾部插入了
    temp = (node*)malloc(sizeof(node));
    temp->val=3;
    head=insertNode(head,temp,2);
    printList(head);


 //    插入第二个元素,后面有个三,所以这里就是中间位置插入了
    temp = (node*)malloc(sizeof(node));
    temp->val=2;
    head=insertNode(head,temp,2);
    printList(head);
}

void testMonotonousInsert()
{

    node* head = NULL;
    node* temp = (node*)malloc(sizeof(node));
    temp->val=1;

    head = monotonousInsertnode(head,temp);
    printList(head);

    temp = (node*)malloc(sizeof(node));
    temp->val=3;
    head=monotonousInsertnode(head,temp);
    printList(head);

    temp = (node*)malloc(sizeof(node));
    temp->val=2;
    head=monotonousInsertnode(head,temp);
    printList(head);

    temp = (node*)malloc(sizeof(node));
    temp->val=4;
    head=monotonousInsertnode(head,temp);
    printList(head);

    temp = (node*)malloc(sizeof(node));
    temp->val=8;
    head=monotonousInsertnode(head,temp);
    printList(head);

    temp = (node*)malloc(sizeof(node));
    temp->val=-1;
    head=monotonousInsertnode(head,temp);
    printList(head);
}

void testDelete()
{

    node* p = NULL;
    printf("create list: \t\n");
    //创建链表0~5
    p = initList();
    printList(p);

    // 删除第一个元素0
    p= deleteNode(p,1);
    printList(p);

   //删除中间元素
    p= deleteNode(p,5);
    printList(p);

   //删除末尾元素9
    p= deleteNode(p,8);
    printList(p);

}

希望对大家能有所帮助。

图片来源:编程导航算法通关村第一期

具体来源:算法通关村第一关——链表—青铜挑战

作者:余秋文章来源地址https://www.toymoban.com/news/detail-620426.html

到了这里,关于算法学习-链表-level1的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包