(注:以下练习中调用的均为带头结点的单链表,读者可以通过“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;
}