线性结构之单链表

//List.h

/*****************************************
头插		尾插		显示		头删		尾删		
按值插入	按位置插入		查找		长度				
逆序		清除		摧毁		初始化	排序
按位置删除		按值删除
****************************************/

//代码可以进一步优化

#ifndef LIST_H_
#define LIST_H_
#include <stdio.h>


typedef int ElementType;
typedef enum
{
	false_,
	true_
}bool_;

//链表的各节点类型
typedef struct Node
{
	ElementType data;
	struct Node *next;
}Node, *pNode;

//链表的管理结构
typedef struct List
{
	Node *first;	//指向头结点
	Node *last;		//指向最后一个节点,用于在某些时候避免不必要的遍历,如尾部插入
	int	  size;		//链表除头结点的个数
}List, *pList;


bool_ init(List *mylist);
bool_ push_fornt(List *mylist, ElementType e);
bool_ push_back(List *mylist, ElementType e);
void show(List mylist);
bool_ pop_fornt(List* mylist, ElementType *e);
bool_ pop_back(List* mylist, ElementType *e);
bool_ insert_val(List *mylist, ElementType e);
bool_ insert_pos(List *mylist, int i, ElementType e);
Node *find(List mylist, ElementType e, bool_ precursor);
int  length(List mylist);
void reverse(List *mylist);
void clear(List *mylist);
void destroy(List *mylist);
void sort(List *mylist);
bool_ delete_pos(List *mylist, int i, ElementType *e);
bool_ delete_val(List *mylist, ElementType e);

#endif //LIST_H_


//List.c

#include "List.h"
#include "stdlib.h"

bool_ init(List *mylist)
{
	mylist->last = mylist->first = (Node *)malloc(sizeof(Node));
	if( NULL == mylist->first )
	{
		return false_;
	}
	mylist->first->next = NULL;	
	mylist->first->data = -1;
	mylist->size = 0;
	return true_;
}

bool_ push_fornt(List *mylist, ElementType e)
{
	Node *p = (Node *)malloc(sizeof(Node));
	if( NULL == p )
		return false_;
	p->next = NULL;
	p->data = e;

	p->next = mylist->first->next;
	mylist->first->next = p;
	if( 0 == mylist->size )	
		mylist->last = p;	//链表为空时,新节点也是尾节点
	mylist->size++;
	return true_;
}

bool_ push_back(List *mylist, ElementType e)
{
	Node *s = NULL;
	Node *p = (Node *)malloc(sizeof(Node));
	if( NULL == p )
		return false_;
	p->data = e;
	p->next = NULL;

	mylist->last->next = p;		
	mylist->last = p;			//注意更改尾指针
	mylist->size++;
	return true_;
}

void show(List mylist)
{
	Node *p = mylist.first->next;
	while(NULL != p)
	{
		printf("%d->", p->data);
		p = p->next;
	}
	printf("NULL\n");
	printf("尾节点的值为%d\n", *mylist.last);
}

bool_ pop_fornt(List* mylist, ElementType *e)
{
	if( 0 == mylist->size)	
	{
		printf("链表为空\n");
		return false_;
	}
	Node *p = mylist->first->next;
	mylist->first->next = p->next;
	*e = p->data;
	free(p);

	if( 1== mylist->size )		//亦可通过比较p与last指针判断
		mylist->last = mylist->first;	//处理尾指针
	mylist->size--;
	return true_;
}

bool_ pop_back(List* mylist, ElementType *e)
{
	if( 0 == mylist->size )	
	{
		printf("链表为空\n");
		return false_;
	}
	Node *p = mylist->first;
	while(p->next != mylist->last)
		p = p->next;				//寻找尾节点前驱节点

	*e = mylist->last->data;
	free(mylist->last);
	mylist->last = p;
	p->next = NULL;
	mylist->size--;
	return true_;
}

bool_ insert_val(List *mylist, ElementType e)	//此函数的先决条件:链表中已存在节点的数据域值必须有序
{
	if( 0 == mylist->size )
		return push_back(mylist, e);
	Node *v = (Node *)malloc(sizeof(Node));
	if( NULL == v )
		return false_;
	v->next = NULL;
	v->data = e;

	Node *p = mylist->first;
	while(NULL != p->next && p->next->data < e)	//寻找位置,找到后p的数据域值小于e,p的后继数据域大于e
		p = p->next;		
	if( NULL == p->next )
		mylist->last = p;		//尾指针
	v->next = p->next;		//使存有e的节点在p的原后继节点之前,p节点之后
	p->next = v;
	mylist->size++;
	return true_;
}

//指定头结点为第0个位置,在第1个位置插入,则插入完成后的第1个位置即为新节点
bool_ insert_pos(List *mylist, int i, ElementType e)
{
	if( i < 1 )
	{
		printf("输入位置小于1, 已插入为第一个节点\n");
		return push_fornt(mylist, e);
	}
	if( i > mylist->size + 1 )
	{
		 printf("输入的位置大于链表范围,已插入为尾节点\n");
		 return push_back(mylist, e);
	}

	Node *v = (Node *)malloc(sizeof(Node));
	if( NULL == v )
		return false_;
	v->data = e;
	v->next = NULL;

	Node *p = mylist->first;
	for(int j = 1; j < i; j++) //寻找合适的位置
	{
		p = p->next;		
	}
	v->next = p->next;
	p->next = v;
	mylist->size++;
	return true_;
}

Node  *find(List mylist, ElementType e, bool_ precursor)	//precursor为真时返回e节点的前驱节点指针值
{
	if( 0 == mylist.size )
		return NULL;
	Node *p = mylist.first;
	while(NULL != p->next && p->next->data != e)
		p = p->next;
	if( NULL == p->next )
		return NULL;
	else
		return precursor ? p : p->next;
}

int  length(List mylist)
{
	return mylist.size;
}

//将链表分成两个链表(链表1有头结点与1节点,链表2为剩余节点的链表)后,将链表2的节点逐个头插入链表1
void reverse(List *mylist)
{
	if( 0 == mylist->size || 1 == mylist->size )
		return ;
	Node *p = mylist->first->next;
	Node *q = p->next;

	p->next = NULL;		//拆分链表
	mylist->last = p;	//处理尾指针

	while(NULL != q)	//将p的节点逐个插入到头结点之后
	{
		p = q;			//p指向当前意图插入的节点
		q = q->next;	//q继续持有链表2
		p->next = mylist->first->next;	//按计划插入
		mylist->first->next = p;
	}
}

void clear(List *mylist)
{
	if( 0 == mylist->size )
		return ;
	Node *p = mylist->first->next;
	mylist->last = mylist->first;	//尾指针
	while( NULL != p)				
	{
		mylist->first->next = p->next;
		free(p);
		p = mylist->first->next;
	}
	mylist->size = 0;			//!!!
}

void destroy(List *mylist)
{
	clear(mylist);
	free(mylist->first);
	mylist->first = mylist->last = NULL;
	
}
//拆分后按序插入,还是跟之前一样拆成两个链表,链表1只含头结点和1节点,链表2含后续节点
void sort(List *mylist)
{
	if( 0 == mylist->size || 1 == mylist->size )
		return ;
	Node *p = mylist->first->next;
	Node *q = p->next;	//q指向链表2
	mylist->last = p;	//尾指针
	p->next = NULL;		//拆分链表
	Node *s = mylist->first;	//s指向链表1

	while(NULL != q)	//将链表2的节点逐个插入到链表1
	{
		while(NULL != s->next && s->next->data < q->data)	//以链表2中的首个节点的数据域去根据顺序查它应该位于链表1的什么位置
		{
			s = s->next;
		}
		if( NULL == s->next )	//链表1中的全部节点数据域都小于q节点
			mylist->last = q;	//处理尾指针
		p = q;					//用p指向待插入节点
		q = q->next;			//q继续持有链表2
		p->next = s->next;		//按计划插入
		s->next = p;
		s = mylist->first;		//令s重新指向链表1
	}
}

bool_ delete_pos(List *mylist, int i, ElementType *e)
{
	int j = 0;
	Node *p = mylist->first;
	Node *q = NULL;
	if( 0 == mylist->size )
	{
		printf("链表为空\n");
		return false_;
	}
	if( i < 1 || i > mylist->size )
	{
		printf("指定的 删除位置不合法,请重新选择\n");
		return false_;
	}
	for(j = 1; j < i; j++)
	{
		p = p->next;
	}
	q = p->next;		//目标删除节点
	p->next = q->next;	
	*e = q->data;
	if( NULL == q->next )		//当q为尾节点
		mylist->last = p;		//	尾
	free(q);
	mylist->size--;
	return true_;
}

bool_ delete_val(List *mylist, ElementType e)
{
	Node * p = NULL, *q = NULL;
	if( NULL == ( p = find(*mylist, e, true_)) )	//查找目标节点的前驱节点
	{
		printf("需要删除的节点不存在\n");
		return false_;
	}
	q = p->next;				//目标节点
	p->next = q->next;
	if( NULL == q->next )		
		mylist->last = p;		//	尾
	free(q);
	mylist->size--;
	return true_;
}





//main.c

/*****************************************
头插		尾插		显示		头删		尾删
按值插入	查找		长度		按值删除		排序
逆序		清除		摧毁		初始化	按位置插入
按位置删除
****************************************/


#include "List.h"

int main(int argc, char**argv)
{
	int s = 0;
	ElementType e;
	List mylist;
	init(&mylist);
	while(1)
	{
		printf("/******************************************************/\n");
		printf("1头插		2尾插		3显示		4头删			5尾删\n");
		printf("6按值插入	7查找		8长度		9按值删除		10排序\n");
		printf("11逆序		12清除		13摧毁		14按位置删除		15按位置插入\n");
		printf("16初始化								17退出\n");
		printf("/******************************************************/\n");
		printf("请选择操作, -1退出\n");
	
		if( 0 == scanf_s("%d", &s) )
			break;

		switch(s)
		{
		case 1:
			printf("请输入待插入的值, -1退出\n");
			while (scanf_s("%d", &e), e != -1)
				push_fornt(&mylist, e);
			break;
		case 2:
			printf("请输入待插入的值, -1退出\n");
			while (scanf_s("%d", &e), e != -1)
				push_back(&mylist, e);
			break;
		case 3:
			show(mylist);
			break;
		case 4:
			if( false_ != pop_fornt(&mylist, &e))
				printf("被删除的值是%d\n", e);
			break;
		case 5:
			if (false_ != pop_back(&mylist, &e))
				printf("被删除的值是%d\n", e);
			break;
			break;
		case 6:
			printf("请输入待插入的值, -1退出\n");
			while (scanf_s("%d", &e), e != -1)
				insert_val(&mylist, e);
			break;
		case 7:
			printf("请输入需查找的值\n");
			scanf_s("%d", &e);
			printf("返回待查值的前驱节点?否:0,是:非0\n");
			scanf_s("%d", &s);
			if( NULL == find(mylist, e, s) )
				printf("查找的值不存在\n");
			break;
		case 8:
			printf("链表长度为%d\n", length(mylist));
			break;
		case 9:
			printf("请输入待删除的值\n");
			scanf_s("%d", &e);
			delete_val(&mylist, e);
			break;
		case 10:
			sort(&mylist);
			break;
		case 11:
			reverse(&mylist);
			break;
		case 12:
			clear(&mylist);
			break;
		case 13:
			destroy(&mylist);
			break;
		case 14:
			printf("请输入待删除位置\n");
			scanf_s("%d", &s);
			if( false_ != delete_pos(&mylist, s, &e) )
				printf("被删除的值为%d\n", e);
			break;
		case 15:
			printf("请输入待插入位置\n");
			scanf_s("%d", &s);
			printf("请输入待插入值");
			scanf_s("%d", &e);
			insert_pos(&mylist, s, e);
			break;
		case 16:
			init(&mylist);
			break;
		case 17:
			goto exit;
		default:
			printf("选择有误,请从新选择\n");
			break;
		}

	}

exit:
	return 1;
}











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值