双向循环链表

头文件:

#ifndef __LINK_h
#define __LINK_h

#include<stdio.h>
#include<stdlib.h>

typedef struct link{
	int data;
	struct link *next;
	struct link *prev;
}link_t, *plink_t;


plink_t create_node(int d);
void insert_tail(plink_t p, plink_t node);
void del_node(plink_t node);
void update(plink_t old, plink_t new);
//操作
//==============================
//函数
plink_t link_init();
void link_insert_head(plink_t p, int d);
void display(plink_t p);
void link_insert_tail(plink_t p, int d);
void link_del(plink_t p, int d);
void link_update(plink_t head, int old, int new);
#endif

主函数代码:

#include "link.h"


int main(void){
	plink_t head;
	head = link_init();
	printf("头节点初始化完成\n");
	
	//输入数据,并根据数据形成节点,头插和尾插
	//temp只是为了跳出循环
	int temp, data;
	while(1){
		temp = scanf("%d", &data);
		if(temp == 0){
			break;
		}
		//头插法
		link_insert_head(head, data);
		display(head);	
	}
	
	getchar();  
	printf("开始尾插操作\n");
	while(1){
		temp = scanf("%d", &data);
		if(temp == 0){
			break;
		}
		//尾插法
		link_insert_tail(head, data);
		display(head);	
	}
	getchar();  
	printf("开始删除操作\n");
	while(1){
		temp = scanf("%d", &data);
		if(temp == 0){
			break;
		}
		
		link_del(head, data);
		display(head);	
	}
	getchar();  
	printf("开始替换操作\n");
	int new;
	while(1){
		printf("输入被替换的旧数据:");
		temp = scanf("%d", &data);
		if(temp == 0){
			break;
		}
		printf("输入替换的新数据");
		temp = scanf("%d", &new);
		if(temp == 0){
			break;
		}
		link_update(head, data, new);
		display(head);	
	}
	
	
	return 0;
}

函数代码:

#include "link.h"

//初始化操作
plink_t create_node(int d){
	plink_t node = (plink_t)malloc(sizeof(link_t));
	if(NULL == node){
		perror("malloc");
		return NULL;
	}
	
	node->data = d;
	node->next = node;
	node->prev = node;
	
	return node;
}

//插入操作
void insert_tail(plink_t p, plink_t node){
	node->next = p->next;
	node->prev = p;
	p->next->prev = node;
	p->next = node;
}

//删除操作
void del_node(plink_t node){
	node->prev->next=node->next;
    node->next->prev=node->prev;
    
    node->prev=node;
    node->next=node;
    free(node);   
}

//替换操作
void update(plink_t old, plink_t new){
	new->next = old->next;
	new->prev = old->prev;
	new->prev->next = new;
	new->next->prev = new;
	free(old);
	
}

//=====================================

//初始化函数
plink_t link_init(){
	return create_node(-1);
}

//头插函数
void link_insert_head(plink_t p, int d){
	plink_t node = create_node(d);
	if(NULL == node){
		return;
	}
	
	insert_tail(p, node);
	return;
}

//尾插函数
void link_insert_tail(plink_t p, int d){
	plink_t node = create_node(d);
	if(NULL == node){
		return;
	}
	
	insert_tail(p->prev, node);
	//return;
}

//删除函数
void link_del(plink_t p, int d){
	plink_t head = p;
	while(p->next != head){
		p = p->next;
		if(p->data == d){
			del_node(p);
			return;
		}
	}
	printf("没有找到");
}

//替换函数
void link_update(plink_t p, int old, int new){
	plink_t head = p;
	while(p->next != head){
		p = p->next;
		if(p->data == old){
			plink_t new_node = create_node(new);
			if(NULL == new_node){
				return;
			}
			update(p, new_node);
			return;
		}
}
}
//遍历函数
void display(plink_t p){
	plink_t head = p;
	while(p->next != head){
		p = p->next;
		printf ("%d ", p->data);
	}
	printf("\n");	
}

段错误的出现:

        在替换函数中,若是没有最后一个return,则会继续执行while循环,但是update函数会将p指向了一个无效地址,也就是free(p)操作,所以会报段错误
        但如果注释掉free(p)这一步,那么它就不会报段错误,因为它还有指向前趋结点和指向后继节点的关系,还是能找到p的地址,也就会继续运行while循环 
        注意的是,这时候的替换操作会全部替换掉后续所有一样的数字,比如1 2 3 3 2 1,将3替换成4,它会全部替换,即1 2 4 4 2 1
        此时,想替换单个数字,则需要加上return跳出循环。

插入操作和替换操作:

        先将新的结点指向原本链表中的两个相连结点,再断开原本相连的两个结点,将它们指向新结点
        需要注意的是!3、4不能和1、2调换位置,如果先执行  p->next = node后再执行    node->next = p->next就会失败,因为p->next指向的结点已经发生改变,原本链表中的成员关系已经发生了改变
        思考:按理说,1和2能够互换,3和4能够互换,12和34之间不能互换,但是3能和12互换。因为没影响到后面的指针域改变,但为了减少错误的出现概率,还是按照以下方式编写
            node->next = p->next;
            node->prev = p;
            p->next->prev = node;
            p->next = node;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值