循环链表和单项链表的差异
单向链表的最后一个结点指针域是空的,而循环链表 最后一个指针域不为空,重新再一次指向头结点的位置
单向链表为何要增加头节点
- 便于首元结点处理
- 便于空表和非空表的统一处理
循环链表的创建
- 第一次创建
- 已经创建,新增数据
判断第一个创建:YES : ->新结点next->自身,NO->链表结尾的位置,尾结点next->新结点,新的结点next=头结点(首元结点)
方法1:
/* 循环链表的创建方式有两种情况 1.判断是否第一次创建链表:
YES->创建一个新结点,并使得新结点的next 指向自身; (*lt)->next = (*lt);
NO-> 找链表尾结点,将尾结点的next = 新结点. 新结点的next = (*lt); */
FunctionType CreateList (CharlesLinkList *lt){
int item;
CharlesLinkList temp = NULL;
CharlesLinkList target = NULL;
printf("请输入结点的值,输入0结束\n");
while (1) {
scanf("%d",&item);
if (item == 0) break;
if (*lt == NULL) {
*lt = (CharlesLinkList)malloc(sizeof(Node));//创建结点
if (*lt == NULL) return ERROR;//如果为空,则不往下执行
(*lt)->data = item;//赋值操作(输入的数字赋值给新创建的结点item)
(*lt)->next = *lt;//新结点==本身
}else{
//1:遍历,找最后一个结点
/*如果target->next != *lt,target = target->next*/
for (target = *lt; target->next != *lt; target = target->next);
//2.创建一个新结点
temp = (CharlesLinkList)malloc(sizeof(Node));
if (temp) return ERROR;
//3.往data里面存储刚刚输入的数据
temp->data = item;
temp->next = *lt;//让temp->next指向首元节点
target->next = temp; } }
return SUCCESS;
}方法2:
//后插法创建
FunctionType CreateList2 (CharlesLinkList *lt){
int item;
CharlesLinkList temp = NULL;
CharlesLinkList target = NULL;
CharlesLinkList r = NULL;
printf("请输入结点的值,输入0结束\n");
while (1) {
scanf("%d",&item);
if (item == 0) break;
if (*lt == NULL) {
*lt = (CharlesLinkList)malloc(sizeof(Node));//创建结点
if (*lt == NULL) return ERROR;//如果为空,则不往下执行
(*lt)->data = item;//赋值操作(输入的数字赋值给新创建的结点item)
(*lt)->next = *lt;//新结点==本身
r = *lt;
}else{
//2.创建一个新结点
temp = (CharlesLinkList)malloc(sizeof(Node));
if (temp) return ERROR;
//3.往data里面存储刚刚输入的数据
temp->data = item;
temp->next = *lt;//让temp->next指向首元节点
r->next = temp;
r = temp;
}
}
return SUCCESS;
}
打印方法:
void show(CharlesLinkList p){
//如果链表是空
if(p == NULL){
printf("打印的链表为空!\n");
return;
}else{
CharlesLinkList temp;
temp = p;
do{
printf("%5d",temp->data);
temp = temp->next;
}while (temp != p);
printf("\n");
}
}循环链表插入数据
实现逻辑顺序
如果插入的位置为place==1时,则属于插入首元结点,所以需要特殊处理
- 创建新结点temp,并判断是否创建成功,成功则赋值,否则返回ERROR;
- 找到链表最后的结点_尾结点,
- 让新结点的next 执行头结点.
- 尾结点的next 指向新的头结点;
- 让头指针指向temp(临时的新结点)
插入的位置为place != 1时(其他位置)
- 创建新结点temp,并判断是否创建成功,成功则赋值,否则返回ERROR;
- 先找到插入的位置,如果超过链表长度,则自动插入队尾;
- 通过target找到要插入位置的前一个结点, 让target->next = temp;
- 插入结点的前驱指向新结点,新结点的next 指向target原来的next位置 ;
Status ListInsert(CharlesLinkList *L, int place, int num){
CharlesCharlesLinkList temp ,target;
int i;
if (place == 1) {
temp = (CharlesLinkList)malloc(sizeof(Node));
if (temp == NULL) {
return ERROR;
}
temp->data = num;
for (target = *L; target->next != *L; target = target->next);
temp->next = *L;
target->next = temp;
*L = temp;
}else {
temp = (CharlesCharlesLinkList)malloc(sizeof(Node));
if (temp == NULL) {
return ERROR;
}
temp->data = num;
for ( i = 1,target = *L; target->next != *L && i != place - 1; target = target->next,i++) ; temp->next = target->next;
target->next = temp;
}
return OK;
}
循环链表删除元素
Status CharlesLinkListDelete(CharlesLinkList *L,int place){
CharlesLinkList temp,target;
int i;
//temp 指向链表首元结点
temp = *L;
if(temp == NULL) return ERROR;
if (place == 1) {
//1.如果删除到只剩下首元结点了,则直接将*L置空;
if((*L)->next == (*L)){
(*L) = NULL;
return OK;
}
//2.链表还有很多数据,但是删除的是首结点;
//2.1 找到尾结点, 使得尾结点next 指向头结点的下一个结点 target->next = (*L)->next;
//2.2 新结点做为头结点,则释放原来的头结点
for (target = *L; target->next != *L; target = target->next);
temp = *L;
*L = (*L)->next;
target->next = *L;
free(temp);
}else{
//如果删除其他结点--其他结点
//1. 找到删除结点前一个结点target
//2. 使得target->next 指向下一个结点
//3. 释放需要删除的结点temp
for(i=1,target = *L;target->next != *L && i != place -1;target = target->next,i++) ;
temp = target->next;
target->next = temp->next;
free(temp);
}
return OK;
}循环链表查询值
int selectValue(CharlesLinkList L,int value){
int i = 1; CharlesLinkList p;
p = L; //寻找链表中的结点 data == value
while (p->data != value && p->next != L) {
i++;
p = p->next;
}
//当尾结点指向头结点就会直接跳出循环,所以要额外增加一次判断尾结点的data == value;
if (p->next == L && p->data != value) {
return -1;
}
return i;
}main 函数执行
int main(int argc, const char * argv[]) {
CharlesLinkList head;
int place,num;
int iStatus;
//iStatus = CreateList(&head);
iStatus = CreateList2(&head);
printf("原始的链表:\n");
show(head);//
printf("输入要插入的位置和数据用空格隔开:");
// scanf("%d %d",&place,&num);
// iStatus = ListInsert(&head,place,num);
// show(head);
printf("输入要删除的位置:");
scanf("%d",&place);
CharlesLinkListDelete(&head,place);
show(head);
printf("输入你想查找的值:");
scanf("%d",&num);
place=findValue(head,num);
if(place!=-1)
printf("找到的值的位置是place = %d\n",place);
else
printf("没找到值\n");
return 0;
}打印结果: