循环与不循环区别
单向链表:只有一个指向下一个节点的指针。
优点:单向链表增加删除节点简单。遍历时候不会死循环;
缺点:只能从头到尾遍历。只能找到后继,无法找到前驱,也就是只能前进。
适用于节点的增加删除。
双向链表:有两个指针,一个指向前一个节点,一个后一个节点。
优点:可以找到前驱和后继,可进可退;
缺点:增加删除节点复杂,需要多分配一个指针存储空间。
适用于需要双向查找节点值的情况
下面讲解双向循环链表的一般写法:
#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
#define ture 1
#define false 0
typedef unsigned char bool;
typedef struct list{
struct list *prev;
int data;
struct list *next;
}List;
List *CreatList(void)
{
List *head = (List *)malloc(sizeof(List));
if(head == NULL)
{
return (List *)ERROR;
}
head->prev = head;
head->next = head;
return head;
}
List *CreatNodeForList(int n)
{
List *node = (List *)malloc(sizeof(List));
if(node == NULL)
{
return (List *)ERROR;
}
node->next = NULL;
node->prev = NULL;
node->data = n;
return node;
}
/**通过表头插入***********/
static bool InsetNodeToListByHead(List *head,int n)
{
if(head == NULL)
{
return ERROR;
}
List *node = CreatNodeForList(n);
node->prev = head;//第一步:连线,新结点的上一个是头
node->next = head->next;//第二步:连线,新结点的下一个是头的下一个
head->prev->next = node;//第三步:头的上一个的下一个是新结点
head->next = node;//第四步:头的下一个是新结点
return OK;
}
/**通过表尾部插入*********/
static bool InsetNodeToListByTail(List *head,int n)
{
if(head == NULL)
{
return ERROR;
}
List *node = CreatNodeForList(n);
List *last = head;
while(last->next != head)
{
last = last->next;
}
head->prev = node;
node->next = head;
last->next = node;
node->prev = last;
return OK;
}
/**指定位置删除结点********/
static bool SpecifyLocationToDelete(List *head,int dele)
{
List *dlnode = head->next;//指定结点指针
List *dlnodep = head;//指定结点前一个结点的指针
while(dlnode->data != dele)
{
dlnodep = dlnode;
dlnode = dlnodep->next;
if(dlnode->next == head)
{
printf("\r\n该结点不存在,无法删除!\r\n");
return ERROR;
}
}
dlnodep->next = dlnode->next;
dlnode->next->prev = dlnodep;
free(dlnode);
dlnode = NULL;
printf("\r\n删除成功\r\n");
return OK;
}
/**搜索指定元素*********/
static bool SearchSpecifyElement(List *head,int seek)
{
List *sknode = head->next;//指定结点指针
List *sknodep = head;//指定结点前一个结点的指针
int record = 1;
while(sknode->data != seek)
{
sknodep = sknode;
sknode = sknodep->next;
record++;
if(sknode == head)
{
printf("\r\n不存在该元素\r\n");
return ERROR;
}
}
printf("\r\n存在该元素,是第%d个结点\r\n",record);
return OK;
}
/**修改指定的元素********/
static bool ModifySpecifyElement(List *head,int mod,int elmt)
{
List *monode = head->next;//指定结点指针
List *monodep = head;//指定结点前一个结点的指针
int record = 1;
while(monode->data != mod)
{
monodep = monode;
monode = monodep->next;
record++;
if(monode == head)
{
printf("\r\n不存在该元素,无法修改\r\n");
return ERROR;
}
}
monode->data = elmt;
printf("\r\n存在该元素,是第%d个结点,可以修改\r\n",record);
return OK;
}
/**打印链表中的元素******/
static bool PrintfList(List *head)
{
List *print = head->next;
while(print != head)
{
printf("->%d",print->data);
print = print->next;
}
printf("\n");
return OK;
}
static int AddNumberToLink(void)
{
int number;
fprintf(stdout,"请输入数据存入链表中,输入0则结束\r\n");
scanf("%d",&number);
return number;
}
/**菜单***************/
static void Menu(void)
{
printf("+===========================================+\n");
printf("| 1.表头插入元素 2.表尾插入元素 |\n");
printf("+===========================================+\n");
printf("| 3.删除指定元素 4.修改指定元素 |\n");
printf("+===========================================+\n");
printf("| 5.搜索指定元素 6.打印双向链表 |\n");
printf("+===========================================+\n");
printf("| 0.退出 |\n");
printf("+===========================================+\n");
}
int main(int argc,char **argv)
{
List *head = CreatList();
int rel = AddNumberToLink();
while(rel)
{
InsetNodeToListByHead(head,rel);
rel = AddNumberToLink();
}
Menu();
int choose = 1;
while(choose)
{
printf("\r\n请输入你的选择\r\n");
scanf("%d",&choose);
int tmp,temp;
switch(choose){
case 1:{
printf("\r\n请输入要插入的元素\r\n");
scanf("%d",&tmp);
InsetNodeToListByHead(head,tmp);
}break;
case 2:{
printf("\r\n请输入要插入的元素\r\n");
scanf("%d",&tmp);
InsetNodeToListByTail(head,tmp);
}break;
case 3:{
printf("\r\n请输入要删除的元素\r\n");
scanf("%d",&tmp);
SpecifyLocationToDelete(head,tmp);
}break;
case 4:{
printf("\r\n请输入要修改的元素\r\n");
scanf("%d",&tmp);
printf("\r\n请输入新的元素\r\n");
scanf("%d",&temp);
ModifySpecifyElement(head,tmp,temp);
}break;
case 5:{
printf("\r\n请输入您要搜索的元素\r\n");
scanf("%d",&tmp);
SearchSpecifyElement(head,tmp);
}break;
case 6:{
PrintfList(head);
}break;
default:
break;
printf("\n");
Menu();
}
printf("\n");
Menu();
}
return OK;
}