您的位置:首页 > 其它

实现单链表的一些操作

2018-03-29 10:35 381 查看
头文件(linklist.h)
#pragma once

#include <stdio.h>
#include <windows.h>
#include <stddef.h>
#include <assert.h>
typedef int listtype;
typedef struct linklist
{
listtype data;
struct linklist* next;
}Linklist,*listpoint;

void linklist_init(listpoint* headpoint);//初始化
void linklist_pushback(listpoint* pphead, listtype data);//尾插
listpoint new_listnode(listtype data);//开辟节点
void linklist_popback(listpoint* pphead);//尾删
void linklist_pushhead(listpoint* phead, listtype data);//头插
void destroy(listpoint head);//释放内存
void linklist_pophead(listpoint* head);//头删
void linklist_print(listpoint head);//打印链表
void linklist_insert(listpoint* head,size_t pos,const listtype data);//任意位置插入
void linklist_pop(listpoint* head, size_t pos);//任意位置删除
listpoint linklist_find(const listpoint head, const listtype to_find);//查找值的地址
void LinkListReversePrint(listpoint head);//逆序打印單鏈表
void LinkListInsertBefore(listpoint* head,listpoint pos,listtype value);//不允许遍历链表, 在 pos之前插入
listpoint Linklistfind(listpoint head, size_t place);//查找結點
void Linklistsort(listpoint pHead);//冒泡排序
listpoint LinkListReverse(listpoint* head);//鏈表逆置
listpoint LinkListMerge(listpoint* list1, listpoint* list2);//合并鏈表
int Linklisthascycle(listpoint head);//判斷是否有環
listpoint FindListKNode(listpoint head, size_t k);//找到倒數第K個節點
listpoint EraseLastKNode(listpoint head, size_t k);//刪除倒數第k個節點
size_t GetCycleLen(listpoint head);//如果鏈表帶環,求出它的長度
listpoint GetCycleEntry(listpoint head);//如果鏈表帶環,求出環的入口
listpoint HasCross(listpoint head1, listpoint head2);//判断链表是否相交并求交点
listpoint HasCross1(listpoint head1, listpoint head2);//判断链表是否相交并求交点(两个不带环的链表)
listpoint HasCross2(listpoint head1, listpoint head2);//判断链表是否相交并求交点(两个带环的链表)

实现函数(linklist.c)
#include "linklist.h"

void destroy(listpoint head)
{
free(head);
}

listpoint Linklistfind(listpoint head, size_t place)//查找結點
{
assert(head);
listpoint ret = head;
while (--place)
{
ret = ret->next;
}
return ret;
}

listpoint new_listnode(listtype data)//建立新的节点
{
listpoint newnode = (listpoint)malloc(sizeof(Linklist));
assert(newnode);
newnode->data = data;
newnode->next = NULL;
return newnode;
}

void linklist_print(listpoint head)//打印
{
for (; head != NULL; head = head->next)
{
printf("%d ", head->data);
}
}

void linklist_init(listpoint* headpoint)//初始化链表
{
*headpoint = NULL;
}

void linklist_pushback(listpoint* pphead, listtype data)//尾插
{
assert(pphead);
if (*pphead == NULL)
{
*pphead = new_listnode(data);
}
else
{
listpoint tail = *pphead;
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = new_listnode(data);
}
}

void linklist_popback(listpoint* pphead)//尾删
{
assert(pphead);
if (*pphead == NULL)
{
printf("尾删时链表为空\n");
system("pause");
exit(1);
}
if ((*pphead)->next == NULL)
{
destroy(*pphead);
*pphead = NULL;
}
else
{
listpoint tmp = *pphead;
while (tmp->next->next != NULL)
{
tmp = tmp ->next;
}
destroy(tmp->next);
tmp->next = NULL;
}
}

void linklist_pushhead(listpoint* phead, listtype data)//头插
{
assert(phead);
listpoint tmp = *phead;
*phead = new_listnode(data);
(*phead)->next = tmp;
}

void linklist_pophead(listpoint* head)//头删
{
assert(head);
if (*head == NULL)
{
printf("头删时链表为空\n");
system("pause");
exit(1);
}
listpoint tmp = (*head)->next;
destroy(*head);
*head = tmp;
}

void linklist_insert(listpoint* head,size_t pos,const listtype data)//任意位置插入
{
size_t list_count = 0;
size_t count = 0;
listpoint tmp = *head;
assert(head);
while (tmp != NULL)
{
tmp = tmp->next;
list_count++;
}

if (list_count == 0)
{
printf("任意位置插入时链表为空\n");
system("pause");
exit(1);
}

if (pos > list_count || pos == 0)
{
printf("任意位置插入时插入位置不合法\n");
system("pause");
exit(1);
}

if (pos == 1)
{
linklist_pushhead(head,data);
}
else
{
listpoint tmp1 = NULL;
tmp = *head;
for (; count < pos - 2; count++)
{
tmp = tmp->next;
}
tmp1 = tmp->next;
tmp->next = new_listnode(data);
tmp->next->next = tmp1;
}
}

void linklist_pop(listpoint* head, size_t pos)//任意位置删除
{
size_t count = 0;
assert(head);
if (*head == NULL)
{
printf("任意位置删除时链表为空,无法删除!");
exit(1);
}
listpoint tmp = *head;
while (tmp != NULL)
{
count++;
tmp = tmp->next;
}
if (pos > count || pos == 0)
{
printf("任意位置删除时,位置不合法\n");
exit(1);
}
if(pos == 1)
{
linklist_pophead(head);
}
else
{
tmp = *head;
pos -= 2;
while (pos--)
{
tmp = tmp->next;
}
listpoint tmp1 = tmp->next->next;
destroy(tmp->next);
tmp->next = tmp1;
}
}

listpoint linklist_find(const listpoint head, const listtype to_find)
{
if (head == NULL)
{
return NULL;
}
listpoint tmp = head;
while (tmp->next != NULL)
{
if (tmp->data == to_find)
{
return tmp;
}
tmp = tmp->next;
}
return NULL;
}
void LinkListReversePrint(listpoint head)//逆序打印單鏈表
{
assert(head);
listpoint cur = NULL;
listpoint tail = NULL;
while (tail != head)
{
cur = head;
while (cur->next != tail)
{
cur = cur->next;
}
printf("%d ", cur->data);
tail = cur;
}
}

void LinkListInsertBefore(listpoint* head, listpoint pos, listtype value)//不允许遍历链表, 在 pos之前插入
{
assert(head);
if (*head == NULL)
{
return;
}
listtype temp;
listpoint newnode = new_listnode(value);
newnode->next = pos->next;
pos->next = newnode;
temp = newnode->data;
newnode->data = pos->data;
pos->data = temp;
}

void Linklistsort(listpoint pHead)//冒泡排序鏈表
{
if (NULL == pHead)
{
return;
}
else
{
listpoint Tail = NULL;
listpoint Flag = NULL;
while (Flag != pHead)
{
Tail = Flag;
Flag = pHead;
listpoint Pre = pHead;
while (Pre->next != Tail)
{
listpoint Cur = Pre->next;
if (Pre->data > Cur->data)
{
listtype dTemp = Pre->data;
Pre->data = Cur->data;
Cur->data = dTemp;
Flag = Pre->next;
}
Pre = Pre->next;
}
}
}
}

listpoint LinkListReverse(listpoint* head)//鏈表逆置
{
assert(head);
if (*head == NULL)
{
return NULL;
}
listpoint ret = NULL;
listpoint tail = NULL;
listpoint cur = *head;
while (tail != *head)
{
cur = *head;
while (cur->next != tail)
{
cur = cur->next;
}
tail = cur;
//linklist_pushhead(&ret, cur->data);//調用头插
linklist_pushback(&ret, cur->data);
}
return ret;
}

listpoint LinkListMerge(listpoint* list1, listpoint* list2)//合并鏈表
{
assert(list1);
assert(list2);
if (*list1 == NULL)
{
return *list2;
}
if (*list2 == NULL)
{
return *list1;
}
listpoint cur1 = *list1;
listpoint cur2 = *list2;
listpoint new_head = NULL;
listpoint tail = NULL;
while (cur1 != NULL && cur2 != NULL)
{
if (cur1->data <= cur2->data)
{
linklist_pushback(&new_head, cur1->data);
cur1 = cur1->next;
}
else
{
linklist_pushback(&new_head, cur2->data);
cur2 = cur2->next;
}
}
if (*list1 != NULL)
{
tail = new_head;
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = cur1;
}
else
{
tail = new_head;
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = cur2;
}
return new_head;
}

int Linklisthascycle(listpoint head)//判斷是否有環
{
if (head == NULL)
{
return 0;
}
listpoint fast = head;
listpoint slow = head;
if (head->next == NULL)
{
return 0;
}
while (fast != NULL)
{
fast = fast->next->next;
slow = slow->next;
if (fast == slow)
{
return 1;
}
if (fast == NULL)
{
return 0;
}
if (fast->next == NULL)
{
return 0;
}
}
return 0;
}

listpoint FindListKNode(listpoint head, size_t k)//找到倒數第K個節點
{
if (head == NULL)
{
return NULL;
}
listpoint fast = head;
listpoint slow = head;
while (k--)
{
if (fast == NULL)
{
return NULL;
}
fast = fast->next;
}
while (fast != NULL)
{
fast = fast->next;
slow = slow->next;
}
return slow;
}

listpoint EraseLastKNode(listpo
4000
int head, size_t k)//刪除倒數第k個節點
{
if (head == NULL)
{
return NULL;
}
listpoint find_node = NULL;
listtype temp = 0;
find_node = FindListKNode(head, k);
temp = find_node->data;
find_node->data = find_node->next->data;
find_node->next->data = temp;
listpoint p_temp = find_node->next->next;
destroy(find_node->next);
find_node->next = p_temp;
return head;
}

size_t GetCycleLen(listpoint head)//如果鏈表帶環,求出它的長度
{
if (head == NULL)
{
return 0;
}
size_t count = 1;
listpoint fast = head;
listpoint slow = head;
while (fast != NULL)
{
fast = fast->next->next;
slow = slow->next;
if (fast == slow)
{
break;
}
}
while (fast->next != slow)
{
count++;
fast = fast->next;
}
return count;
}

listpoint GetCycleEntry(listpoint head)//如果鏈表帶環,求出環的入口
{
if (head == NULL)
{
return NULL;
}
listpoint start = head;
listpoint fast = head;
listpoint slow = head;
while (fast != NULL)
{
fast = fast->next->next;
slow = slow->next;
if (fast == slow)
{
break;
}
}
while (start != fast)
{
start = start->next;
fast = fast->next;
}
return start;
}

listpoint HasCross1(listpoint head1, listpoint head2)//判断链表是否相交并求交点
{
if (head1 == NULL || head2 == NULL)
{
return NULL;
}
//两个不带环的链表
listpoint cur1 = head1;
listpoint cur2 = head2;
while (cur1->next != NULL)
{
cur1 = cur1->next;
}
cur1->next = cur2;
int ret = Linklisthascycle(head1);
if (ret == 1)
{
printf("两链表相交\n");
}
else
{
printf("两链表不相交\n");
return NULL;
}
return GetCycleEntry(head1);
}

listpoint HasCross2(listpoint head1, listpoint head2)//判断链表是否相交并求交点
{
listpoint cur1 = head1;
listpoint cur2 = head2;
listpoint ret = NULL;
if (GetCycleEntry(head1) == GetCycleEntry(head2))
{
ret = GetCycleEntry(head1);
while (cur1->next != ret)
{
cur1 = cur1->next;
}
cur1->next = cur2;
ret = GetCycleEntry(head1);
return ret;
}
else
{
listpoint ret1_head1 = GetCycleEntry(head1);
listpoint ret2_head2 = GetCycleEntry(head2);
listpoint fast = ret1_head1;
listpoint slow = ret2_head2;
while (fast != slow)
{
fast = fast->next->next;
slow = slow->next;
}
return fast;
}
return NULL;
}

listpoint HasCross(listpoint head1, listpoint head2)//判断链表是否相交并求交点
{
if (head1 == NULL || head2 == NULL)
{
return NULL;
}
size_t flag = 0;
listpoint ret_note = NULL;
if (Linklisthascycle(head1) + Linklisthascycle(head2) == 2)
{
size_t len = GetCycleLen(head1);
listpoint ret_enter_head1 = GetCycleEntry(head1);
listpoint ret_enter_head2 = GetCycleEntry(head2);
while (len--)
{
ret_enter_head1 = ret_enter_head1->next->next;
ret_enter_head2 = ret_enter_head2->next;
if (ret_enter_head1 == ret_enter_head2)
{
flag = 1;
}
}
if (flag == 1)
{
ret_note = HasCross2(head1, head2);
return ret_note;
}
return NULL;
}
else if (Linklisthascycle(head1) + Linklisthascycle(head2) == 0)
{
ret_note = HasCross1(head1, head2);
return ret_note;
}
else
{
return NULL;
}
}

测试函数(test.c)
#include "linklist.h"

int main()
{
listpoint node = NULL;
listpoint node2 = NULL;
listpoint node3 = NULL;
listpoint node4 = NULL;
listpoint node5 = NULL;
listpoint node6 = NULL;
listpoint tmp = NULL;
listpoint ret = NULL;
int RET = 0;
linklist_init(&node);//初始化
linklist_pushback(&node, 5);//尾插
linklist_pushback(&node, 5);//尾插
linklist_pushback(&node, 6);//尾插

linklist_init(&node2);//初始化
linklist_pushback(&node2, 2);//尾插
linklist_pushback(&node2, 4);//尾插
linklist_pushback(&node2, 6);//尾插

linklist_init(&node3);//初始化
linklist_pushback(&node3, 1);//尾插
linklist_pushback(&node3, 3);//尾插
linklist_pushback(&node3, 5);//尾插

linklist_init(&node4);//初始化
linklist_pushback(&node4, 1);//尾插
linklist_pushback(&node4, 2);//尾插
linklist_pushback(&node4, 3);//尾插
linklist_pushback(&node4, 4);//尾插
linklist_pushback(&node4, 5);//尾插
linklist_pushback(&node4, 6);//尾插

linklist_init(&node5);//初始化
linklist_pushback(&node5, 1);//尾插
linklist_pushback(&node5, 2);//尾插
linklist_pushback(&node5, 3);//尾插
linklist_pushback(&node5, 4);//尾插
linklist_pushback(&node5, 5);//尾插
linklist_pushback(&node5, 6);//尾插

linklist_init(&node6);//初始化
linklist_pushback(&node6, 1);//尾插
linklist_pushback(&node6, 2);//尾插
linklist_pushback(&node6, 3);//尾插
linklist_pushback(&node6, 4);//尾插
linklist_pushback(&node6, 5);//尾插
linklist_pushback(&node6, 6);//尾插

linklist_popback(&node);//尾删
linklist_popback(&node);//尾删
linklist_pushhead(&node, 7);//头插
linklist_pushhead(&node, 7);//头插
linklist_pophead(&node);//头删
linklist_insert(&node, 1, 9);//任意位置插入
linklist_insert(&node, 2, 15);//任意位置插入
linklist_insert(&node, 3, 20);//任意位置插入
linklist_pop(&node, 1);//任意位置删除
linklist_pop(&node, 2);//任意位置删除
linklist_print(node);//打印
LinkListReversePrint(node);//逆序打印單鏈表
ret=Linklistfind(node,1);//查找結點
LinkListInsertBefore(&node,ret,20);//不允许遍历链表, 在 pos之前插入
ret = Linklistfind(node,1);//查找結點
LinkListInsertBefore(&node, ret, 30);//不允许遍历链表, 在 pos之前插入
node=LinkListReverse(&node);//鏈表逆置
Linklistsort(node);//冒泡排序
ret = LinkListMerge(&node2, &node3);//合并鏈表
RET=Linklisthascycle(node);//判斷是否有環
ret=FindListKNode(node,2);//找到倒數第K個節點
node = EraseLastKNode(node, 5);//刪除倒數第k個節點
node = EraseLastKNode(node, 2);//刪除倒數第k個節點
node = EraseLastKNode(node, 2);//刪除倒數第k個節點
listpoint cur = node4;
while (cur->next != NULL)
{
cur = cur->next;
}
cur->next = node4->next;
RET = Linklisthascycle(node4);//判斷是否有環
RET=GetCycleLen(node4);//如果鏈表帶環,求出它的長度
ret=GetCycleEntry(node4);//如果鏈表帶環,求出環的入口
node6->next->next = node5->next->next;
ret=HasCross(node5,node6);//判断链表是否相交并求交点
free(node);
system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: