【数据结构】单链表练习

(注:以下练习中调用的均为带头结点的单链表,读者可以通过“https://blog.csdn.net/xing1584114471/article/details/83004289”带头结点的单链表进行学习了解)

/*
(一)将带头节点的单链表改成不带头节点的单链表。
*/

//构造结点
typedef struct Node1
{
	ElemType data;//结点数据域
	struct Node1 *next;//结点后继指针
}Node1;

//构造链表
typedef struct LinkList1
{
	Node1 *head;//头指针
	int count;//标记链表中的结点个数
}LinkList1, *Plist1;

//初始化单链表函数
void InitLinkList1(Plist1 list)
{
	assert(list != NULL);
	list->count = 0;
	list->head = NULL;
}

//购买结点
static Node1 *BuyNode( ElemType val, Node1 *next)
{
	Node1* s = (Node1*)malloc(sizeof(Node1) * 1);
	assert(s != NULL);

	s->data = val;
	s->next = next;
	return s;
}
//插入结点函数
void InsertLinkList1(Plist1 list, ElemType val, int pos)
{
	assert(list != NULL);
	if(pos < 0 || pos > list->count)
	{
		printf("pos is error!\n");
		return ;
	}

	if(list->head == NULL)//第一个结点插入
	{
		list->head = BuyNode(val, NULL);
		list->count++;
		return ;
	}

	Node1* p = list->head;
	while( pos > 1)
	{
		p = p->next;
		pos--;
	}

	if(pos == 0)//考虑头插的情况(pos == 1)
	{
		Node1* s = BuyNode(val, p);
		list->head = s;
		list->count++;
		return ;
	}

	Node1* s = BuyNode(val, p->next);
	p->next = s;
	list->count++;
}

//插头结点函数
void InsertHeadLinkList1(Plist1 list, ElemType val)
{
	assert(list != NULL);
	InsertLinkList1(list, val, 0);
}

//插尾结点函数
void InsertTailLinkList1(Plist1 list, ElemType val)
{
	assert(list != NULL);
	InsertLinkList1(list, val, list->count );
}

//删除结点函数
void DeleteLinkList1(Plist1 list, int pos)
{
	assert(list != NULL);
	if(pos < 1 || pos > list->count)
	{
		printf("pos is error!\n");
		return ;
	}
	Node1* p = list->head;
	if( pos == 1)//考虑删除头结点
	{
		list->head = p->next;
		free(p);
		list->count--;
		return ;
	}
	while( pos > 2)
	{
		p = p->next;
		pos--;
	}	
	Node1* s = p->next;
	p->next = s->next;
	free(s);
	list->count--;
}

//删头结点函数
void DeleteHeadLinkList1(Plist1 list)
{
	assert(list != NULL);
	DeleteLinkList1(list, 1);
}

//删尾结点函数
void DeleteTailLinkList1(Plist1 list)
{
	assert(list != NULL);
	DeleteLinkList1(list, list->count);
}

//顺序输出函数
void Show1(Plist1 list)
{
	assert(list != NULL);
	Node1 *p = list->head;
	while(p != NULL)
	{
		printf("%3d",p->data);
		p = p->next;
	}
	printf("\n");
}

//销毁函数
void Destroy1(Plist1 list)
{
    assert(list != NULL);
	Node1 *p = list->head;
	while( list->count > 0)  //采用count遍历循环
	{
		DeleteHeadLinkList1(list);
	}
	printf("OK\n");
}

/*
(二)已知递增有序的单链表 A,B 和C 分别存储了一个集合,设计算法实现 A:= A∪(B∩C) ,并使求解结构A 仍保持递增。要求算法的时间复杂度为 O(|A|+|B|+|C|)。其中,|A|为集合A 的元素个数。
*/

void Combine_Intersect(Plist list_a, Plist list_b, Plist list_c)
{
	assert(list_a != NULL);
	assert(list_b != NULL);
	assert(list_c != NULL);

	int pos = 0;
	Node *p_a = list_a->head.next;
	Node *p_b = list_b->head.next;
	Node *p_c = list_c->head.next;

	while(p_b != NULL && p_c != NULL)
	{
		if( p_b->data > p_c->data)
		{
			p_c = p_c->next;
		}
		else if( p_c->data > p_b->data)
		{
			p_b = p_b->next;
		}
		else
		{
			int val = p_b->data;
			while(1)
			{
				if(p_a == NULL )
				{
					InsertTailLinkList(list_a, val);
					break;
				}
				else if(p_a->data < val)
				{
					pos++;
					p_a = p_a->next;
				}
				else if(p_a->data == val)
				{
					p_a = p_a->next;
					pos++;
					break;
				}
				else
				{
					InsertLinkList(list_a, val, pos);
					pos++;
					break;
				}
			}
			p_b = p_b->next;
			p_c = p_c->next;
		}
	}
}

/*
试写一算法,对单链表实现就地逆置,请注意时间复杂度最好能达到O(n)
*/

void InversionLinkList2(Plist list)
{
	assert(list != NULL);
	struct Node *m = list->head.next;
	struct Node *f = NULL;

	if( m == NULL) //判断链表是否只有一个头结点,如果只有一个结点就直接返回
	{
		printf("error\n");
		return ;
	}
	struct Node *l = m->next;
	while(1)
	{
		m->next = f;
		f = m;
		m = l;
		if( m == NULL)
		{
			break;
		}
		l = l->next;
	}
	list->head.next = f;
}

函数测试

int main()
{
/*
不带头结点的单链表函数测试
****************************************************
	LinkList1 list;
	InitLinkList1(&list);
	for( int i = 0; i < 10; i++)
	{
		InsertLinkList1(&list, i * 10, i);
	}
	Show1(&list);
	InsertLinkList1(&list, 22, 8);
	InsertTailLinkList1(&list, 88);
	Show1(&list);
	printf("***********************************\n");
	DeleteLinkList1(&list, 2);
	Show1(&list);
	DeleteLinkList1(&list, 4);
	Show1(&list);
	DeleteHeadLinkList1(&list);
	Show1(&list);
	DeleteTailLinkList1(&list);
	Show1(&list);
	printf("***********************************\n");
	Show1(&list);
****************************************************
*/

/*
Combine_Intersect函数测试
****************************************************
	Linklist list_a;
	Linklist list_b;
	Linklist list_c;
	InitLinkList(&list_a);
	InitLinkList(&list_b);
	InitLinkList(&list_c);
	int j = 1;
	int t = 3;
	for( int i = 0; i < 10; i++)
	{
		InsertLinkList(&list_a, j + t , i);
		InsertLinkList(&list_b, i + j , i);
		InsertLinkList(&list_c, t + i , i);
		j++;
		t++;
	}
	Show(&list_a);
	Show(&list_b);
	Show(&list_c);
	printf("****************************************\n");
	Combine_Intersect(&list_a, &list_b, &list_c);
	Show(&list_a);
****************************************************
*/

/*
InversionLinkList函数测试
****************************************************
	Linklist list;
	InitLinkList(&list);

	for( int i = 0; i < 15; i++)
	{
		InsertLinkList(&list, i , i);
	}
	Show(&list);
	printf("**************************");
	InversionLinkList2(&list);
	Show(&list);
****************************************************
*/
	return 0;
}

 

你可能感兴趣的:(数据结构,习题,习题练习---单链表)