#include<stdio.h>
#include<stdlib.h> //系统函数头文件
/*链表存储结构的定义*/
typedef struct CLinkList
{
int data;
struct CLinkList *next;
} node;
/*****************************************/
/*操作 */
/*****************************************/
/*初始化循环链表*/
void ds_init(node **pNode)
{
int item;
node *temp;
node *target;
printf("输入节点的值,输入0完成初始化\n");
while(1)
{
scanf("%d",&item);
fflush(stdin); //清除缓冲区 ,保证输入正常
if(item==0)
return;
if((*pNode)==NULL)
{/*循环链表中只有一个节点*/
*pNode=(node*)malloc(sizeof(struct CLinkList));
if(!(*pNode))
exit(0); //无条件退出函数
(*pNode)->data=item;
(*pNode)->next=*pNode;
}
else
{
/*找到next指向第一个结点的结点*/
for(target=(*pNode);target->next!=(*pNode);target=target->next)
; //将指针指向下一个对象,直到指向头结点
/*生成一个新的结点 */
temp=(node *)malloc(sizeof(struct CLinkList)); //分配内存空间
if(!temp) //分配失败退出
exit(0);
temp->data=item; //将输入的值赋给temp
temp->next=*pNode; //将新的数据元素的指针指向头结点
target->next=temp; //原来的最后一个元素的指针指向新的元素
}
}
}
/*插入结点*/
/*参数:链表的第一个结点,插入的位置*/
void ds_insert(node **pNode, int i) //i为插入的元素的插入位置
{
node *temp; //定义变量
node *target;
node *p;
int item;
int j=1;
printf("输入要插入结点的值:"); //给插入结点赋值
scanf("%d",&item);
if(i==1)
{
//新插入的结点作为第一个结点
temp=(node*)malloc(sizeof(struct CLinkList));//分配内存
if(!temp) //失败退出
exit(0);
temp->data=item; //把插入的值赋给temp
/*寻找到最后一个节点*/
for(target=(*pNode);target->next!=(*pNode);target=target->next)
;
temp->next=(*pNode); //把temp的指针指向头结点
target->next=temp; //把最后一个结点的指针指向temp,因为temp要变成第一个结点
*pNode=temp; //完全替换,把头结点的位置让给temp
}
else
{
target=*pNode; //把target赋给头结点
for(;j<(i-1);++j) //进行遍历,知道target为要插入元素的位置的前一个元素的位置
{
target=target->next;
}
temp=(node *)malloc(sizeof(struct CLinkList));
if(!temp)
exit(0);
temp->data=item; //把插入的值赋给temp
p=target->next; //利用中介p来装载要插入的位置的上个位置的指针
target->next=temp; //把这个指针指向temp
temp->next=p; //然后再调出p,完成衔接 temp 就有了前驱和后继
}
}
/*删除节点*/
void ds_delete(node **pNode,int i) //i为要删除的结点的位置
{
node *target;
node *temp;
int j=1;
if(i==1)
{
//删除的是第一个结点
/*找到最后的一个结点*/
for(target=*pNode;target->next!=*pNode;target=target->next)
;
temp=*pNode; //当删除的是第一个结点的时候,把temp代表头结点
*pNode=(*pNode)->next; //头结点变为原来头结点指向的那个元素的指针,变为新的头结点
target->next=*pNode; //最后一个结点的指针指向新的头结点
free(temp); //释放原来的头结点,也相当于删除
}
else
{
target=*pNode; //target代表头结点
for(;j<i-1;++j) //进行遍历,要target指向要删除位置的元素
target=target->next;
temp=target->next; //temp承载要删除的元素
target->next=temp->next; //把target的指针指向要删除的元素的指针,直接跳过被删除元素
free(temp); //释放temp,相当于删除
}
}
/*返回结点所在位置*/
int ds_search(node *pNode,int elem) //elem相当于要寻找的元素
{
node *target;
int i=1;
for(target=pNode;target->data!=elem&&target->next!=pNode;++i)
target=target->next; //让target当头结点,进行指向,当碰到元素elem时,停止,i记载位置
if(target->next==pNode) //如果是头结点,返回0,否则,返回 i的值
return 0;
else
return i;
}
/*遍历*/
void ds_traverse(node *pNode)
{
node *temp;
temp=pNode; //temp作为头结点
printf("**********链表中的元素********");
do
{
printf("%4d",temp->data); //进行输出
} while((temp=temp->next)!=pNode); //直到temp的指针指向头结点
printf("\n");
}
int main()
{
node *pHead=NULL;
char opp;
int find;
printf("1.初始化列表\n\n2.插入结点\n\n3.删除节点\n\n4.返回结点位置\n\n5.遍历链表\n\n0.退出\n\n请输入你的操作");
while(opp!='0')
{
scanf("%c",&opp);
switch(opp)
{
case'1':
ds_init(&pHead);
printf("\n");
ds_traverse(pHead);
break;
case'2':
printf("输入需要插入结点的位置:");
scanf("%d",&find);
ds_insert(&pHead,find);
printf("在位置%d插入值后:\n",find);
ds_traverse(pHead);
printf("\n");
break;
case'3':
printf("输入需要删除的结点位置:");
scanf("%d",&find);
ds_delete(&pHead,find);
printf("删除第%d个结点后:",find);
ds_traverse(pHead);
printf("\n");
break;
case'4':
printf("你要查找倒数第几个结点的值:");
scanf("%d",&find);
printf("元素%d所在位置:%d\n",find,ds_search(pHead,find));
printf("\n");
break;
case'5':
ds_traverse(pHead);
printf("\n");
break;
case'0':
exit(0);
}
}
return 0;
}
新手刚刚入门数据结构,用了一个上午了解,认识,理解了循环链表,虽然懂了,可无奈小编智力有限,费了不少时间,不过功夫不负有心人,总算在数据结构大门挤出了一点门缝,看到一个特别好的实例,有链表的初始化,插入,删除,查看,遍历,感觉受益匪浅,想与大家分享,所有理解都加在注释里面了,大家可以边看代码,边理解。