单链表的基本操作

      单链表最为人熟悉,随便一搜都讲的很好,所以还是不要献丑,直接上代码吧。

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



typedef struct LNode 
{
	void *data;			// 这里设成指针型是因为 这里储存是要操作的数据的首地址,通过该数据域的地址(4个字节)操作它,提高效率,而无类型是为了通用
	struct LNode *next;
}NODE;



typedef struct
{
	NODE *head;			//头指针	头指针是指向头结点的指针 而头结点是单链表第一个结点之前的一个结点,数据域可以不存储任何信息,指针域指向第一个结点
	NODE *last;			//尾指针
	int length;			
}LinkList;



typedef struct students
{
	char sno[5];
	char name[21];
	int age;
	float score;
}STU;

STU s[6] = {
	{"S001","lin wu",12,90},
	{"S002","xiao ming",13,80},
	{"S003","wang wu",11,100},
	{"S004","xiao hong",14,24},
	{"S005","zhang san",15,45},
	{"S006","li xi",19,90}
};





LinkList *CreateList();																// 创建链表
int AppendList(LinkList *l, void *data, int size);									// 在链表最后追加结点
int InsertList(LinkList *l, int n, void *data, int size);							// 在第 n 个结点之前插入一个结点
void PrintList(LinkList *l, void (* printnode)(void *));							// 打印
NODE *FindBykey(LinkList *l, void *key, int (*compare)(void *, void *));			// 按关键字查找
NODE *FindNode(LinkList *l, void *key, int (*compare)(void *, void *), NODE **pre);	// 查找关键字结点之前的那个结点
int DeleteByKey(LinkList *l, void *key, int (*compare)(void *,void*));				// 按关键字删除
int DeleteByIndex(LinkList *l, int index, void *e, int size);									// 按位置删除,并返回所删结点数据域到 e






void PrintData(void *data)
{
	STU *t = (STU *)data;
	printf("%-5s %-10s %5d %5f\n",t->sno,t->name,t->age,t->score);
}


int CompareByName(void *info, void *name)
{
	STU *t = (STU *)info;
	char *s = (char *)name;
	return strcmp(t->name, s) == 0 ? 1 : 0;
}






int main()
{
	int i;
	LinkList *list = CreateList();
	char name[21];
	NODE *res = NULL;
	STU *e = (STU *)malloc(sizeof(STU));


	for (i = 0; i < 4; ++i)
	{
		AppendList(list, &s[i], sizeof(s[i]));
	}
	PrintList(list, PrintData);
	printf("\n\n");


	InsertList(list, 3, &s[4], sizeof(s[4]));
	PrintList(list, PrintData);
	printf("\n\n");


	res = FindBykey(list, name, CompareByName);
	if (NULL == res)
	{
		printf("Not Find!\n");
	}
	else
	{
		printf("Find!\n");
	}
	printf("\n\n");

	AppendList(list, &s[5], sizeof(s[5]));
	PrintList(list, PrintData);
	printf("\n\n");

	
	DeleteByIndex(list, 1, e, sizeof(STU));
	printf("所删结点的数据:\n");
	printf("%-5s %-10s %5d %5f\n\n",e->sno,e->name,e->age,e->score);
	PrintList(list, PrintData);
	printf("\n\n");


	printf("请输入想要删除的学生名字:");
//	scanf("%s",name);
	gets(name);
	DeleteByKey(list, name, CompareByName);
	PrintList(list, PrintData);
	printf("\n\n");

	return 0;
}


// 创建链表
LinkList *CreateList()
{
	LinkList *l = (LinkList *)malloc(sizeof(LinkList));
	if (NULL == l)
	{
		exit(0);
	}
	memset(l,0,sizeof(LinkList));
	
	NODE *pHead = (NODE *)malloc(sizeof(NODE));
	if (NULL == pHead)
	{
		exit(0);
	}
	memset(pHead, 0, sizeof(NODE));

	l->head = pHead;

	return l;
}


// 在链表最后追加结点
int AppendList(LinkList *l, void *data, int size)
{
	NODE *n = NULL;
	
	if (NULL == l || NULL == data)
	{
		return 0;
	}
	
	n = (NODE *)malloc(sizeof(NODE));
	if (NULL == n)
	{
		return 0;
	}

	n->data = malloc(size);
	if (NULL == n->data)
	{
		free(n);
		return 0;
	}
	memcpy(n->data, data, size);

	if (NULL == l->head->next)
	{
		l->head->next = n;
	}
	else
	{
		l->last->next = n;
	}
	l->last = n;
	n->next = NULL;			// 最后一个结点的指针域指向空 也可以写成l->last->next = NULL;
	l->length++;
	
	return 1;
}


// 在第 n 个结点之前插入一个结点
int InsertList(LinkList *l, int n, void *data, int size)
{
	NODE *p = NULL, *t = NULL;
	int i = 0;

	if (NULL == l || NULL == data || n < 1 || n > l->length)
	{
		return 0;
	}

	p = l->head;
	while (i < n - 1)
	{
		p = p->next;
		++i;
	}

	t = (NODE *)malloc(sizeof(NODE));
	if (NULL == t)
	{
		return 0;
	}
	
	t->data = malloc(size);
	if (NULL == t->data)
	{
		free(t);
		return 0;
	}
	memcpy(t->data, data, size);

	t->next = p->next;
	p->next = t;
	
	l->length++;
	return 1;
}


// 打印
void PrintList(LinkList *l, void (* printnode)(void *))
{
	NODE *p = NULL;
	int i;

	if (NULL == l || NULL == printnode)
	{
		return;
	}
	
	p = l->head->next;

	for (i = 0; i < l->length && NULL != p; ++i)
	{
		printnode(p->data);
		p = p->next;
	}
}


// 按关键字查找
NODE *FindBykey(LinkList *l, void *key, int (*compare)(void *, void *))
{
	NODE *p = NULL;
	int i = 0;

	if (NULL == l || NULL == key || NULL == compare)
	{
		return NULL;
	}

	p = l->head;

	while (i < l->length)
	{
		p = p->next;
		if (1 == compare(p->data, key))
		{
			return p;
		}
		++i;
	}
	
	return NULL;
}


// 查找关键字结点之前的那个结点
NODE *FindNode(LinkList *l, void *key, int (*compare)(void *, void *), NODE **pre)
{
	NODE *p = NULL;
	if (NULL == l || NULL == key || NULL == compare || pre == NULL)
	{
		return NULL;
	}

	p = l->head;
	*pre = NULL;

	while (p)
	{	
		p = p->next;

		if (1 == compare(p->data,key))
		{
			return p;
		}
		*pre = p;
	}

	return NULL;
}


// 按关键字删除
int DeleteByKey(LinkList *l, void *key, int (*compare)(void *,void*))
{
	NODE *p = NULL , *q = NULL;

	p = FindNode(l,key,compare,&q);
	if (NULL == p)
	{
		return 0;
	}

	if (NULL == q)
	{
		l->head->next = p->next;
	}
	else
	{
		q->next = p->next;
	}

	if (p == l->last)
	{
		l->last = q;
	}

	free(p->data);
	free(p);
	l->length--;

	return 1;
}


// 按位置删除,并返回所删结点数据域到 e
int DeleteByIndex(LinkList *l, int index, void *e, int size)
{
	NODE *p = NULL, *q = NULL;
	int i = 0;

	if (NULL == l || index < 1 || index > l->length)
	{
		return 0;
	}
	
	p = l->head;
	while (i < index - 1)
	{
		p = p->next;
		++i;
	}
	
	q = p->next;
//	e = malloc(sizeof(size));
	memcpy(e, q->data, size);
//	e = q->data;

	p->next = q->next;

	free(q->data);
	free(q);
	l->length--;
	return 1;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值