数据结构--双向循环链表C实现

双向链表的优点是可以向前后两个方向遍历,而单链表和循环链表,如果要对某一个元素进行操作,必须找到该元素的前一结点;而双链表就不需要,因为它可以向前遍历,找到前一结点修改它的后缀,同理可以修改后一结点的前缀。

本文代码没有使用哨兵结点实现。


#include <stdio.h>
#include <stdlib.h>

typedef int Mt;

typedef struct Node{
    Mt data;
    struct Node *next;
    struct Node *prior;

}Dlist;

Dlist *CurPosition;

Dlist* init()
{
    Dlist *head=NULL,*p ,*p1;
    int n;
    printf("输入数据数量:\n");
    scanf("%d",&n);
    if(n>0)
    {
        p = (Dlist*)malloc(sizeof(Dlist));
        if(p == NULL){
            printf("内存申请失败!\n");
            return NULL;
        }
        if(head==NULL)
        {
            head = p;
        }
        scanf("%d",&p->data);
        p->next = p;
        p->prior = p;
        p1 = p;
        while (--n>0)
        {
            p= (Dlist*)malloc(sizeof(Dlist));
            scanf("%d",&p->data);
            p1->next = p;
            p->next = p1;
            p->prior = p1;
            p1 = p;
        }
        p1->next = head;
        head->prior = p1;
    }
    CurPosition = head;//返回当前位置。
    return head;

}

void printDlist(Dlist *head)
{
    Dlist *h;
    h=head;
    if(head == NULL)
    {
        printf("该链表为空!\n");
    }else
    {
        while(head!=NULL)
        {
            printf("%d ",head->data);
            head = head->next;
            if(head == h)
               break;
        }
    }

}

Dlist* deleteDlist(Dlist *head)
{
    Dlist *h1,*h2;
    h1 = head;
    while(head!=NULL)
    {
        h2 = head;
        free(head);
        head = h2->next;
        if(h1==head)
        {
            printf("双向链表删除完成!\n");
            break;
        }
    }
    return NULL;
}

int LengthDlist(Dlist *head)
{
    int length =0;
    Dlist *h = head;
    while(head!=NULL)
    {
        length++;
        head = head->next;
        if(head == h)
            break;
    }
    return length;
}

Dlist* insertHead(Dlist* head,Mt num)
{
    Dlist *p;
    p = (Dlist*)malloc(sizeof(Dlist));
    if(p == NULL){
        printf("内存申请失败!\n");
        return head;
    }
    p->data = num;
    if(head == NULL)
    {
        p->next = p;
        p->prior = p;
    }else
    {
        p->next = head;
        p->prior = head->prior;
        head->prior->next = p;
        head->prior = p;
    }
    printf("插入成功!\n");
    return CurPosition = p;
}

Dlist *Taildelete(Dlist *head)
{
    Dlist* h;
    if(head==NULL)
    {
        printf("该链表为空,删除失败!\n");
        return NULL;
    }else if(head == head->next)
    {
        free(head);
        return NULL;//如果只有一个结点,返回NULL
    }else
    {
        h=head->prior;
        head->prior = h->prior;
        h->prior->next = head;
        free(h);
        printf("删除尾部结点完成!\n");
    }
    CurPosition = head->prior;
    return head;
}

Dlist* insertPosition(Dlist* head,int pos,Mt num)
{
    int i;
    int len = LengthDlist(head);
    Dlist *p,*h=head;
    if(pos>len+1)
    {
        printf("插入位置超过链表长度!\n");
        return head;
    }else if(head ==NULL)
    {
        p = (Dlist*)malloc(sizeof(Dlist));
        if(p == NULL){
           printf("内存申请失败!\n");
           return head;
        }
        p->data = num;
        p->next = p;
        p->prior = p;
        return p;
    }else
    {
        p = (Dlist*)malloc(sizeof(Dlist));
        if(p == NULL){
           printf("内存申请失败!\n");
           return head;
        }
        p->data =num;
        if(pos==1)
        {
            p->next = head;
            p->prior = head->prior;
            head->prior->next = p;
            head->prior = p;
            h = p;
        }else if(pos == LengthDlist(head))
        {
            p->next = head;
            p->prior = head->prior;
            head->prior->next = p;
            head->prior = p;
            h = p;
        }else
        {
            for(i=2;i<pos;i++)
            {
                head = head->next;
            }
            p->next = head->next;
            p->prior = head;
            head->next->prior = p;
            head->next = p;

            CurPosition = p;
        }
    }
    return h;
}

Dlist* deletePosition(Dlist* head,int pos)
{
    Dlist* h;
    if(head==NULL)
    {
        printf("该链表为空,删除第%d个位置的元素失败!\n",pos);
        return NULL;
    }else if(pos>LengthDlist(head) || pos<=0)
    {
        printf("删除位置超过链表长度!\n");
        return head;
    }else if(LengthDlist(head)==1)
    {
        free(head);
        return NULL;
    }
    else if(pos == 1)
    {
        h = head->next;
        head->prior->next = head->next;
        h->prior = head->prior;
        free(head);
    }else if(pos == LengthDlist(head))
    {
        h = head;
        head = head->prior;
        h->prior = head->prior;
        head->prior->next = h;
        free(head);
    }else
    {
        h = head;
        while(--pos)
        {
            head = head->next;
        }
        head->next->prior = head->prior;
        head->prior->next = head->next;

        CurPosition = head->next;
        free(head);
    }
    return h;
}

int getPosElement(Dlist *head) //获取当前操作的位置
{
    int Pos=1;
    if(head == CurPosition)
    {
        Pos = 1;
    }else
    {
        while(head!=CurPosition)
        {
            Pos++;
            head = head->next;
        }
    }
    return Pos;
}

int main(int argc, char *argv[]) {
    Dlist *Head=NULL;
    Dlist *CurPosition;
    int Len,Pos;
    Head = init();
    //printDlist(Head);
    //Head = deleteDlist(Head);
    //Len = LengthDlist(Head);
    //printf("该链表长度为:%d\n",Len);
    //printf("从头部插入一个数:\n");
    //Head = insertHead(Head,4);
    //printDlist(Head);
    //Head = Taildelete(Head);
    //Head = insertPosition(Head,3,8);
    Head = deletePosition(Head,2);
    printDlist(Head);
    Len = LengthDlist(Head);
    printf("该链表长度为:%d\n",Len);
    Pos = getPosElement(Head);
    printf("当前操作位置:%d\n",Pos);
    return 0;
}

学习总结:
先看下面的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

char *fuc(char *s)
{
    char str[20]="";
    int i,j;
    for(i=strlen(s)-1,j=0;i>=0;i--,j++)
    {
        str[j]=s[i];
    }
    return str;
}

int main(int argc, char *argv[]) {
    char *s = "hello world";
    char *ch;
    ch = fuc(s); //将s指向的字符数组逆序并返回
    puts(ch);
    printf("\n"); 
    return 0;
}

看似程序没有问题,但是总是纠结为什么得不到正确的结果。深入探讨发现,地址的传递并没有问题,只是地址指向的数据不见了。还是学艺不精啊0.0。原来str数组定义为局部变量,随着函数fuc的结束而结束。所以ch接收到的字符串的首地址已经没有指向想要的字符串了。

一朝被蛇咬,十年怕井绳啊!
于是乎我觉得下面的代码也有问题:

Rlist init(Rlist head) //建立哨兵结点
{
    Rlist p;
    p = (Rlist)malloc(sizeof(struct Node));
    if(errMemory(p))
    {
        head = p;
        p->next =NULL;
        return head;
    }
    return NULL;
}

一个链表的初始化,没错,它是在子函数里面的进行的。但是为什么它的内存空间没有杯释放呢?
原来是malloc函数的原因,该函数主动申请一段内存,内存就不会被系统显性地释放,需要主动调动free函数释放内存0.0。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值