C语言——写双向链表代码及感悟

一、代码

/*
*linkedlist
*2018/11/29:head_insert;tail_insert;reverse;traversal;

*2018/11/30:insert;dele;
*xinchiwu
*/
#include 
#include 
typedef struct linkedlistnode 
{
    struct linkedlistnode *prev;
    char data;
    struct linkedlistnode *next;
}linkedlist;
linkedlist *head, *tail;
void head_insert()//头插入法;通过全局变量,返回头指针和尾指针;
{
    char ch;
    linkedlist *q;
    q = NULL;
    head = NULL;
    tail = NULL;
    printf("请输入头插法要插入的字符:\n");
    ch = getchar();
    while (ch != '\n')
    {
        linkedlist  *s = (linkedlist*)malloc(sizeof(linkedlist));
        if (s != 0)
        {
            s->next = head;
            s->data = ch;
            s->prev = NULL;
            head = s;
            if (s->next == NULL)
            {
                tail = s;
                q = tail;
            }
            else 
            {
                q->prev = s;
                q = q->prev;
            }
            ch = getchar();
        }
    }
}
void traversal()//遍历;通过头指针读取结点数据;
{
    linkedlist *s;
    char ch;
    printf("正序输出的链表如下:\n");
    while (head != NULL)
    {
        ch = head->data;
        printf("%c",ch);
        s = head;
        if (head != NULL)
        {
            head = head->next;
            s->next = NULL;

            free(s);
        }
    }
}
void tail_insert()//尾插入法;通过全局变量,返回头指针和尾指针;
{
    linkedlist *p;
    p = head;
    char ch;
    head = NULL;
    tail = NULL;
    printf("请输入尾插法要插入的字符:\n");
    ch = getchar();
    while (ch != '\n')
    {
        linkedlist  *s = (linkedlist*)malloc(sizeof(linkedlist));
        if (s != 0)
        {
            
                s->prev = p;
                s->data = ch;
                s->next = NULL;
                tail = s;
                ch = getchar();
                if (head == NULL)
                {
                    head = s;
                    p = head;
                }
                else 
                { 
                    p->next = s; 
                    p = p->next;
                }
        }
    }
}
void reversal()//倒序;通过尾指针读取节点数据;
{
    linkedlist *s;
    char ch;
    printf("倒序输出的链表如下:\n");
    while (tail != NULL)
    {
        ch = tail->data;
        printf("%c", ch);
        s = tail;
        if (tail != NULL)
        {
            tail = tail->prev;
            s->prev = NULL;

            free(s);
        }
    }
}
void insert()//向链表中插入节点;n<=0,插在头节点处;n>=链表长度,插在尾结点处;
{
    printf("请输入要插入的位置:\n");
    int n;
    scanf_s("%d", &n);
    linkedlist *s=(linkedlist*)malloc(sizeof(linkedlist));
    linkedlist *p, *q;
    p = q = NULL;
    char ch;
    getchar();
    printf("请输入要插入的字符:\n");
    ch = getchar();
    s ->data= ch;
    if (n <= 1)
    {
        head->prev = s;
        s->next = head;
        s->prev = NULL;
        head = s;
    }
    else
    {
        for (int i = n - 1; i > 0; i--)
        {
            if (i==n-1) 
            {
                p = head;
                q = p->next;
            }
            else 
            {
                if (q->next != NULL)
                {
                    p = p->next;
                    q = q->next;
                }
                else
                {
                    p = p->next;
                    break;
                }
            }
        }
        if (p->next != NULL)
        {
            q->prev = s;
            p->next = s;
            s->next = q;
            s->prev = s;
        }
        else 
        {
            s->next = NULL;
            tail = s;
            s->prev = p;
            p->next = s;
        }
    }
}
void dele()//删除链表中的节点;n<=0,删除头节点处;n>=链表长度,删除尾结点处;
{
    printf("请输入要删除的位置:\n");
    int n;
    scanf_s("%d", &n);
    linkedlist *p, *q, *r;
    p = q = r = NULL;
    if (n <= 1)
    {
        r = head;
        head = head->next;
        head->prev = NULL;
    }
    else
    {
        for (int i = n - 1; i > 0; i--)
        {
            if (i == n - 1)
            {
                p = head;
                r = p->next;
                q = r->next;
            }
            else
            {
                if (q->next != NULL)
                {
                    p = p->next;
                    r = r->next;
                    q = q->next;
                }
                else
                {
                    p = p->next;
                    r = r->next;
                    break;
                }
            }
        }
        if (q->next != NULL)
        {
            q->prev = p;
            p->next = q;
            r->next = NULL;
            r->prev = NULL;
        }
        else
        {
            p->next = NULL;
            r->next = NULL;
            r->prev = NULL;
            tail = p;
        }
    }
    free(r);
    r = NULL;
}
int main() 
{
    
    //tail_insert();
    head_insert();
    insert();
    //dele();
    //traversal();
    reversal();
    getchar();
    char c = getchar();
}


二、感悟

双向链表与单向链表最大的不同,就是有个prev,所以在维护节点之间的关系时,要注意两个方向的连接。相对单链表,双链表的倒序十分容易,但插入和删除并没有太大不同。

你可能感兴趣的:(linux,c,data,structure)