双向动态链表才是关键,直接看例子和图示既就可以,主要是自己会画图,然后根据图来写代码
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;
}