您的位置:首页 > 理论基础 > 数据结构算法

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

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

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

#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。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息