链表的进一步学习

链表的进一步学习

 

 

  阮阮在上周的学习中学会了链表的基本使用方法,但是好奇心很重的它还是忍不住探索链表的一些用法,于是它向它右边的大神鑫鑫请教,
于是热情的鑫鑫就认真的教了它后面的内容

学习内容:

一,反转链表(递归,迭代)

二,打印链表(递归)

三,双向链表

 

一,反转链表:

这个图就是反转链表前后的对比

 后面上代码:

这里就是主函数中的应用:

int main() {
    head = NULL;
    Insert('r', 1);
    Insert('w', 2);
    Insert('t', 3);
    Insert('n', 4);
    Insert('b', 5);
    int n;
    /*scanf_s("%d", &n);
    Delete(n);*/

    Print();
    head = reverse(head);//还有就是发现了没有这个为什么要传会一个头地址呢??
    Print();//print函数在打印的时候是根据头地址进行遍历和打印链表的。
    return 0;
}
struct Node* reverse(struct Node* head) {
    struct Node* current,*prev,*next;
    current = head;
    prev = NULL;//记住创建结点一定要进行初始化,
    while (current != NULL) {
        next = current->next;//这个地方之所以要用next是因为如果直接把current转给前一个,它的下一个结点就会失去
        current->next = prev;
        prev = current;//把之前的那个current变成prev
        current = next;//next就变成了current
    }
    //最后current变成NULL,next也变成NULL,原来的head就变成了prev,也就是最后一个结点变成了头。
    head = prev;
    return head;
}

最后的反转之后的结果是

 

 

成功的反转了链表,反转链表的本质就是把原来链表的结点给断开,然后把这个结点的地址指向上一个节点,但是我这里遇到了一个问题,我直接把结点指向上一个位置后,这个位置下一个地方的地址就丢失了

所以我这里又用一个临时结点来储存下一个结点的地址,然后再将当前结点的位置指向上一个结点,然后就把current的值赋给prev,把next的值赋给current,这样就可以有遍历的效果。然后在最后,current和next'的值全是NULL,将prev的值赋给head,这样head就变成了之前链表的尾部。也就是下面这个图。

 

二,用递归的方式打印链表(反转):


这里就是用前一段时间学习的递归来理解:

void reverseprint(struct Node* p) {//这个是使用递归进行反转打印
    if (p == NULL) {
        return;
    }
    reverseprint(p->next);
    printf("%d", p->data);
}

就是在递归树中,reverseprint不断进行递归,知道p = NULL的时候开始打印,从尾向头开始打印,这里难度不大,但是要记住,一定要有递归的退出条件。

 

 

三,双向链表;

这张图就是双向链表的大体结构

就是在data域之前多了一个prev域来指向上一个位子。

 

下面来讲创建双向链表:

struct Node* getnewnode(int x) {
    struct Node* newnode = (struct Node*)malloc(sizeof(struct Node));
    newnode->data = x;
    newnode->next = NULL;
    newnode->prev = NULL;
    return newnode;//返回newnode的初值
}
void Inverathead(int x) {
    struct Node* newnode = getnewnode(x);
    if (head == NULL) {
        head = newnode;
    }
    head->prev = newnode;
    newnode->next = head;

    head = newnode;
}
void Reverseprint() {
    struct Node* temp = head;
    if (temp == NULL) {
        return;
    }
    while (temp != NULL) {
        temp = temp->next;
    }
    printf("Reverse:");
    while (temp != NULL) {
        printf("%d", temp->data);
        temp = temp->prev;
    }
    printf("\n");

}

 

上面这一段代码三个函数做了三件事,首先创建了一个双向链表,第一个函数就是开辟双向链表所需的内存空间,当然在这之前还要写上相关的双向链表的struct相比于普通链表而言,双向链表就是多了一个指向前一个结点的指针。第二个函数就是创建的过程了,为了便于理解过程如下:

就是一个把你的prev连到我身上,再把我的next连在你身上,就像事两个人左手牵右手,右手牵左手一个道理。最后这个函数就用到了双向链表的特点进行反向打印,其实说白了,就是正向遍历,在temp到最后的时候再来一个方向打印呗,其实蛮简单的。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2021-10-24 15:06  prize  阅读(31)  评论(0)    收藏  举报