数据结构——双向循环链表(二)双向动态链表

双向动态链表才是关键,直接看例子和图示既就可以,主要是自己会画图,然后根据图来写代码

dlist.h  //头文件

#include<stdio.h>
#include<stdlib.h>
typedef struct _node
{
        int data;
        struct  _node* next;
        struct  _node* pre;
}DNode;

void traverseDList(DNode* head);//遍历

DNode* creatDListTail();   //尾插法(基本不用)

DNode* creatDListHead();//头插法

void insertDList(DNode *head,int input);//插入节点

int lenDList(DNode* head); //求长度

DNode* searchDList(DNode* head,int find);  //查找

void deleteDNodeList(DNode * pfind);  //删除节点

void popSortDList(DNode*head);  //排序(交换数据

void popSortDList2(DNode*head);  //排序(交换指针)

void destroyDList(DNode*head);   //销毁链表 

dlist.c   //实现,重点!

#include"dlist.h"
//以下入参性检查省略
void traverseDList(DNode* head)
{
    DNode * th = head;
    th=th->next;
    while(th != head)
    {
        printf("%d\n",th->data);
        th=th->next;
    }
}

DNode* creatDListTail()  //尾插法,这里把创建链表和插入值合在一起了
{
    DNode * head=(DNode*)malloc(sizeof(DNode));
    head->next=head->pre=NULL;
    DNode * th =head;  //找一个head的替身,head不能随便动
    DNode * cur=NULL;//设置一个往下走的指针,只要cur能够开辟,且输入值不为0,就一直往下连
    int input;
    scanf("%d",&input);
    while(input)
    {
        cur=(DNode*)malloc(sizeof(DNode));
        cur->data=input;

        //链接 连上
        th->next=cur;
        cur->pre=th;

        th=cur;//两个指针指向同一节点,以便于继续循环
        scanf("%d",&input);
    }

    cur->next=head;
    head->pre=th;   //形成回环,这里cur和th在同一个节点上,都可以用
    return head;
}

这里实质就是cur指向的新节点如何链接上

DNode* creatDListHead()  
{
    DNode * head=(DNode*)malloc(sizeof(DNode));
    head->next=head; head->pre=head;  //形成一个自己连接自己的环

    return head;
}

void insertDList(DNode *head, int input)  ////头插法,会画就是看图说话
{
    DNode* cur =NULL;
    cur=(DNode*)malloc(sizeof(DNode));
    cur->data=input;

    cur->next=head->next;  //根据图片,就可以看图说话,直接连接
    cur->pre=head;             //注意,这里最好先让新来的节点,先有连接

    head->next=cur;
    cur->next->pre=cur;
}

int lenDList(DNode* head)  //求长度
{
    DNode * th = head;  //由于必须需要head指明一圈的标志,所以需要一个替身
    int len=0;
    th=th->next;            //头节点不存数,首节点开始存
    while(th != head)
    {
        len++;
        th=th->next;
    }
    return len;
}

DNode *searchDList(DNode* head, int find)  //寻找
{
    DNode* clock,*anti;            //一个‘顺时针’转,一个‘逆时针’转
    clock=head->next; anti=head->pre;
    while(clock->pre != anti)  //这里判断两个相反方向是否相遇,在这里有两种情况,
    {
         //一种是两者在同一节点相遇,还有一种是正好错过轮流指向下一个
         //但是两种情况都经历了一个‘相遇 ’,也就是都会遇到clock->pre == anti, clock回头看到了anti
        if(clock->data == find)
            return clock;
        if(anti->data == find)
            return anti;
        if(anti == clock)        //若在同一节点相遇。且这个节点的data不是所要的,返回NULL
            return NULL;
        clock=clock->next;
        anti=anti->pre;
    }
    return NULL;
}

void deleteDNodeList(DNode * pfind)  //删除节点,看图说话
{
    pfind->pre->next=pfind->next;
    pfind->next->pre=pfind->pre;
    free(pfind);
    pfind=NULL;
}

void popSortDList(DNode*head)  //排序  (交换数据的排序)
{
    int len = lenDList(head);
    DNode *p,*q;                      //多引进一个指针方便书写
    for(int i=0;i<len-1;i++)
    {
        p=head->next;
        q=p->next;
        for(int j=0;j<len-1-i;j++)
        {
            if(p->data > q->data)
            {
                p->data ^=q->data;//无参交换
                q->data ^=p->data;
                p->data ^=q->data;
            }
            p=p->next;
            q=q->next;
        }
    }
}

void popSortDList2(DNode*head)  //排序(交换指针)
{
    int len=lenDList(head);
    DNode *p,*q;
    for(int i=0;i<len-1;i++)
    {
        for(int j=0;j<len-1-i;j++)
        {
            p=head->next;
            q=p->next;
            if(p->data > q->data)  //看图说话
            {
                p->pre->next=q;
                q->pre=p->pre;
                p->next=q->next;
                p->pre=q;
                q->next=p;
                p->next->pre=p;

                q=p->next;  //把q p顺序回到原来  p q
                continue;
            }
            p=p->next;
            q=q->next;
        }
    }
}

void destroyDList(DNode*head)   //销毁链表
{
    DNode*t=head;
    head->pre->next=NULL; //把双向链表一圈最后的节点置为空,实际上就是转化为单向链表
    while(head)
    {
        head=head->next;
        free(t);
        t=head;
    }
}
 

main函数

#include <stdio.h>
#include"dlist.h"
int main()
{
#if 0 //尾插
    DNode* head=creatDListTail();
    traverseDList(head);
#endif

#if 1    //头插
    DNode*head=creatDListHead();
    for(int i=0;i<10;i++)
    {
        insertDList(head,i);
    }
    traverseDList(head);
#endif
    DNode * pfind = searchDList(head,1);
    if(pfind ==  NULL)
        printf("find none\n");
    else
    {
         printf("in the list\n");
         deleteDNodeList(pfind);
         traverseDList(head);
    }
    printf("after sort\n");
    popSortDList(head);
    traverseDList(head);

    popSortDList2(head);
    traverseDList(head);

    destroyDList(head);
    return 0;
}
 

猜你喜欢

转载自blog.csdn.net/weixin_42513339/article/details/81191903