单循环链表

//SCList.h

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

//代码可以进一步优化

#ifndef SCLIST_H_
#define SCLIST_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_front(List *mylist, ElementType e);
bool_ push_back(List *mylist, ElementType e);
void show(List mylist);
bool_ pop_front(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 //SCLIST_H_


//SCList.c

#include "SCList.h"
#include "stdlib.h"

/*******************
与单链表无太大差异
只是判断条件由 != NULL 变为了 != 头结点
值得注意的是,循环链表的头结点千万不能搞丢了,即使是指向头结点的指针不能随意乱指
********************/

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

bool_ push_front(List *mylist, ElementType e)
{
	Node *p = (Node *)malloc(sizeof(Node));
	if( NULL == p )
		return false_;
	p->data = e;
	if( 0 == mylist->size )
	{
		mylist->last = p;
		mylist->last->next = mylist->first;	//循环
	}
	p->next = mylist->first->next;
	mylist->first->next = p;
	mylist->size++;
	return true_;
}

bool_ push_back(List *mylist, ElementType e)
{
	Node *p = (Node *)malloc(sizeof(Node));
	if( NULL == p )
		return false_;
	mylist->last->next = p;
	p->data = e;
	p->next = mylist->first;	//循环
	mylist->last = p;
	mylist->size++;
	return true_;
}

void show(List mylist)
{
	Node *p = mylist.first->next;
	while(mylist.first != p)	//标志为头结点
	{
		printf("%d->", p->data);
		p = p->next;
	}
	printf("HEAD\n");
	printf("尾节点的值为%d\n", mylist.last->data);
	printf("尾节点的后继结点 %s 头结点\n", mylist.last->next == mylist.first ? "是" : "不是");
	printf("头结点的值为%d\n", mylist.last->next->data);
}

bool_ pop_front(List* mylist, ElementType *e)
{
	if( 0 == mylist->size )
	{
		printf("链表为空\n");
		return false_;
	}
	Node *p = mylist->first->next;
	if( p == mylist->last )
		mylist->last = mylist->first;	//头结点自循环
	mylist->first->next = p->next;
	*e = p->data;
	free(p);
	mylist->size--;
	return true_;
}

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

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;
	mylist->last = p;	//尾指针
	*e = p->next->data;
	free(p->next);
	p->next = mylist->first;
	mylist->size--;
	return true_;
}

bool_ insert_val(List *mylist, ElementType e)			//此函数的先决条件:链表中已存在节点的数据域值必须有序
{
	Node *p = mylist->first;
	while(p->next != mylist->last && p->next->data < e)
		p = p->next;
	if( p->next == mylist->last && p->next->data < e )	//循环链表中所有节点数据域值均小于e
	{
		return push_back(mylist, e);
	}
	else
	{
		Node *s = (Node *)malloc(sizeof(Node));
		if (NULL == s)
			return false_;
		s->data = e;
		s->next = p->next;
		p->next = s;
		mylist++;
	}
	return true_;
}

//头结点为位置0
bool_ insert_pos(List *mylist, int i, ElementType e)
{
	if( i < 1 )
	{
		printf("位置过小已作为头节点插入\n");
		return push_front(mylist, e);
	}
	if( i > mylist->size + 1 )
	{
		printf("位置过大已作为尾节点插入\n");
		return push_back(mylist, e);
	}
	Node *s = (Node *)malloc(sizeof(Node));
	if( NULL == s )
		return false_;
	s->data = e;
	Node *p = mylist->first;
	for(int j = 1; j < i; j++)
		p = p->next;
	s->next = p->next;
	p->next = s;
	mylist->size++;
	return true_;
}

Node *find(List mylist, ElementType e, bool_ precursor)
{
	if( 0 == mylist.size )
		return NULL;
	Node *p = mylist.first;
	while( p->next != mylist.first && p->next->data != e)
		p = p->next;

	if( p->next->data != e )
		return NULL;
	else
		return precursor ? p : p->next;
}

//还是跟之前一样的做法,将链表分为两个小链表,链表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;
	mylist->last = mylist->first->next;		//处理尾指针
	mylist->last->next = mylist->first;		//链表1自循环循环

	while(q != mylist->first)				//将链表2中的节点逐个头插入链表1
	{
		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;

	while(p != mylist->first)
	{
		mylist->first->next = p->next;
		free(p);
		p = mylist->first->next;
	}
	mylist->last = mylist->first;			//处理尾指针
	mylist->last->next = mylist->first;		//自循环
	mylist->size = 0;
}

void destroy(List *mylist)
{
	clear(mylist);
	free(mylist->first);
	mylist->first = mylist->last = NULL;
}


void sort(List *mylist)
{
	if( 0 == mylist->size || 1 == mylist->size )
		return ;
	Node *p = mylist->first->next;
	Node *q = p->next;

	mylist->last = p;
	mylist->last->next = mylist->first;	//循环
	Node *s = mylist->first;
	while(q != mylist->first)
	{
		p = q;
		q = q->next;
		while(s->next != mylist->first && s->next->data < p->data)
			s = s->next;
		if( s->next == mylist->first )	//链表1中所有节点数据域值均小于p节点数据域
			mylist->last = p;			
		
		p->next = s->next;
		s->next = p;
		s = mylist->first;
	}
	mylist->last->next = mylist->first;	//循环
}

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

bool_ delete_pos(List *mylist, int i, ElementType *e)
{
	if( 0 == mylist->size )
	{
		printf("链表为空\n");
		return false_;
	}
	if( i < 1 || i > mylist->size )
	{
		printf("删除的位置不合法\n");
		return false_;
	}
	Node *p = mylist->first;
	Node *q = NULL;
	for(int j = 1; j < i; j++)
	{
		p = p->next;
	}
	q = p->next;
	*e = q->data;
	p->next = q->next;
	if( q->next == mylist->first )
	{
		mylist->last = p;
		p->next = mylist->first;
	}
	free(q);
	mylist->size--;
	return true_;
}


//main.c

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


#include "SCList.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_front(&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_front(&mylist, &e))
				printf("被删除的值是%d\n", e);
			break;
		case 5:
			if (false_ != pop_back(&mylist, &e))
				printf("被删除的值是%d\n", e);
			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 == 0 ? false_ : true_)))
				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、付费专栏及课程。

余额充值