郝斌数据结构6(双向链表)

双向链表

  郝斌老师课程没有双向链表内容,我参考大话数据结构把双向链表进行简单实现,其实双向链表跟单链表类似,没有特别难的地方,只需要自己画图,把每一步程序的意思弄明白,并不难。
  需要注意的有两个地方:双向链表的插入和删除,插入节点时前驱和后驱赋值顺序,删除节点时前驱和后驱的赋值顺序。另外还有就是遍历的时候,注意终止条件,因为是双向链表,如果不记录头结点,可能会一直循环下去。

#include
#include
#include
#include

typedef struct Node
{
    int data;
    struct Node * prior;
    struct Node * pnext;
}NODE, * PNODE;

PNODE creat_list()
{
    int len = 0;
    int i = 0;
    int val = 0;
    PNODE pHead = (PNODE) malloc(sizeof(NODE));//注意后续释放
    if(NULL == pHead)
    {   
        printf("malloc err!\n");
        exit(-1);
    }   
    PNODE pTail = pHead;
    pTail->prior = NULL;
    pTail->pnext = NULL;
    
    printf("请输入您需要创建的链表节点的个数:len = ");
    scanf("%d",&len);

    printf("请输入第1个节点的数据:val = ");
    scanf("%d",&val);

    PNODE p1 = (PNODE)malloc(sizeof(NODE));
    if(NULL == p1)
    {
        printf("分配失败,程序终止!\n");
        exit(-1);
    }
    p1->data = val;
    pTail->pnext = p1;
    pTail = p1;

    for(i = 2; i <= len; i++)
    {   
        printf("请输入第%d个节点的数据:val = ",i);
        scanf("%d",&val);

        PNODE pNew = (PNODE)malloc(sizeof(NODE));
        if(NULL == pNew)
        {
            printf("分配失败,程序终止!\n");
            exit(-1);
        }
        pNew->data   = val;
        pTail->pnext = pNew; //当前尾节点的pnext指向新节点
        pNew->prior  = pTail;//新节点的prior指向尾节点
        pNew->pnext  = p1;   //新节点的pnext指向头节点
        p1->prior    = pNew; //头节点的prior指向新节点
        pTail        = pNew; //新节点变为尾节点
    }
    return pHead;
}

/* 双链表一般不会为空的,所以判断空的就暂不实现
bool is_empty(PNODE pHead)
{
    if(NULL == pHead->pNext)
        return true;
    else
        return false;
}*/
void traverse_list(PNODE pHead)
{
    PNODE p = pHead->pnext;
    PNODE pHead1 = p;//记录第一个有效节点,防止一直循环下去
    do
    {   
        printf("%d\t", p->data);
        p = p->pnext;
    }while(p != pHead1);   
    printf("\n");
}

int length_list(PNODE pHead)
{
    PNODE p = pHead->pnext;
    PNODE pHead1 = p;//同样是记录首节点,防止死循环
    int len = 0;
    do
    {
        len++;
        p = p->pnext;
    }while(p != pHead1);
    return len;
}

int insert_list(PNODE pHead, int pos, int val)
{
   int i = 0;
   PNODE p = pHead;
   PNODE pEnd = pHead;
    //首先调整p指向的位置
    //其实这地方最好不要插入第一个位置,本实现最后结果是插在最后
   if(pos == 1)
   {
       p = p->pnext;
       PNODE pNew = (PNODE)malloc(sizeof(NODE));
       if(NULL == pNew)
       {
           printf("malloc failed!\n");
           exit(-1);
       }
       pNew->data = val;
       pNew->pnext = p;
       pNew->prior = p->prior;
       p->prior->pnext = pNew;
       p->prior = pNew;

       return true;
   }
   do
   {
       p = p->pnext;
       i++;
   }while(pHead != pEnd && i < pos - 1);
   //这时候p已经指向pos的位置
   if(i > pos-1 )
       return false;

   PNODE pNew = (PNODE)malloc(sizeof(NODE));
   if(NULL == pNew)
   {
       printf("分配内存失败!\n");
       exit(-1);
   }
   pNew->data = val;

   pNew->pnext = p->pnext;//新节点的后驱指向p的后驱
   pNew->prior = p;//新节点的前驱指向p
   p->pnext->prior = pNew;//p的后驱的前驱指向新节点
   p->pnext = pNew;//p的后驱指向新节点

   return true;
}
//只实现了在链表中部的实现,首节点的删除未实现,即pos>=2
int delete_list(PNODE pHead, int pos, int *val)
{
    int i = 0;
    PNODE p = pHead;
    PNODE pHead1 = p;
    do
    {
        p = p->pnext;
        ++i;
    }while(i <= pos-1 && p != pHead1);
    *val = p->data;
    p->pnext->prior = p->prior;//要删除节点p的后驱的前驱指向p的前驱
    p->prior->pnext = p->pnext;//要删除节点p的前驱的后驱指向p的后驱
    free(p);
    return true;
}
int main(void)
{
    PNODE pHead;
    int val;
    pHead = creat_list();
    traverse_list(pHead);
    int ret;
    ret = insert_list(pHead, 2, 11);
    if(ret < 0)
    {
        printf("插入失败,ret = %d\n",ret);
        return -1;
    }
    traverse_list(pHead);

    delete_list(pHead,2,&val);
    traverse_list(pHead);
    
    return 0;
}

你可能感兴趣的:(C语言,算法数据结构,郝斌老师数据结构学习笔记)