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

来源:互联网 发布:小说站源码 编辑:程序博客网 时间:2024/04/20 04:42

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

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


#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
原创粉丝点击