一、链表与数组的比较:
(1)数组:
数组优点:a.可以利用偏移地址来访问元素,效率高,为O(1);
b.可以使用折半查找元素,效率较高;
数组缺点:a.空间连续,存储效率低;
b.插入和删除元素效率比较低;
(2)链表:
链表优点:a.插入和删除元素不需要移动其余元素,效率高,为O(1);
b.不要求连续空间,空间利用效率高;
链表缺点:a.不提高随机访问元素的机制;
b.查找元素和搜索元素的效率低,最快情况下为O(1),平常情况为O(N);
二、链表与数组在空间中储存图示:
(1)数组的储存方式:是连续存放的
(2)链表的储存方式:不是连续存放的
三、代码区:
(链表的实现与链表的面试题的实现)
头文件(#LinkList.h)
#ifndef _LINK_H__
#define _LINK_H__
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
typedef int Datatype;
typedef struct Node
{
Datatype data;
struct Node*next; //指向下一个地址的指针
//struct Node*last; //指向上一个地址的指针
}Node, *pNode;
void InitLinkList(pNode *head); //初始化函数
void PushFront(pNode *head,Datatype d); //头插
void PopFront(pNode*head); //头删
void PushBack(pNode *head, Datatype d); //尾插
void PopBack(pNode*head); //尾删
void Reverse(pNode*head); //逆序
void Insert(pNode*head,Datatype d,int pos); //指定位置插入数据
void DelNotTail(pNode pos); //删除无头的不为结尾的任意一个节点
pNode Find(pNode head,Datatype d); //查找函数
pNode FindMidNode(pNode plist); //找中间节点的位置
pNode CheckCycle(pNode plist); //检测是否带环
int GetCircleLength(pNode meet); //求环的长度
pNode GetCircleEntryNode(pNode meet, pNode plist); //获取环的进入点
pNode CheckCross(pNode p1, pNode p2); //两条链的交点
void JosephCycle(pNode plist, int k); //约瑟夫环
void DelKNode(pNode plist, int k); //删除倒数第k个节点
void SortList(pNode head); //冒泡排序
void Reverseshow(pNode head); //逆序打印
pNode Merge(pNode plist1, pNode plist2); //两条有序链的合并,合并之后依然有序
void Display(pNode head); //显示函数
void DestroyList(pNode*head); //释放空间
#endif //
函数(LinkList.c)
#include"Linklist.h"
void InitLinkList(pNode *head) //初始化函数
{
*head = NULL;
}
void PushFront(pNode*head, Datatype d) //头部插入数据函数
{
assert(head);
pNode p = malloc(sizeof(Node));
memset(p, 0, sizeof(Node));
p->data = d;
p->next = NULL;
p->next = *head;
*head = p;
}
void PopFront(pNode*head) //头部删除数据函数
{
pNode pur = *head;
if (pur == NULL)
return;
else
{
*head = pur->next;
free(pur);
}
}
void PushBack(pNode *head,Datatype d) //尾部插入数据函数
{
pNode pur = *head;
pNode p = malloc(sizeof(Node));
memset(p, 0, sizeof(Node));
p->data = d;
p->next = NULL;
if (pur == NULL)
{
*head = p;
}
else
{
while (pur->next != NULL)
{
pur = pur->next;
}
pur->next = p;
}
}
void PopBack(pNode *head) //尾部删除数据函数
{
assert(head);
pNode pur = NULL;
pNode cur = *head;
if (*head == NULL)
return;
while (cur->next != NULL)
{
pur = cur;
cur = cur->next;
}
if (pur!= NULL)
{
pur->next = NULL;
free(cur);
}
else
{
free(cur);
*head = NULL;
}
}
void Insert(pNode*head,Datatype d,int pos) //指定位置插入函数
{
pNode pur = NULL;
pNode cur = *head;
pNode p = malloc(sizeof(Node));
p->data = d;
p->next = NULL;
if (*head == NULL)
{
*head = p;
return;
}
if (pos == 1)
{
p->next = *head;
*head = p;
}
else
{
while (pos - 1)
{
pur = cur;
cur = cur->next;
pos--;
}
p->next = cur;
pur->next = p;
}
}
void Reverse(pNode*head) //逆序函数
{
pNode cur = *head;
pNode newhead = NULL;
pNode tail = NULL;
if (cur == NULL || cur->next == NULL)
return;
while (cur!=NULL)
{
newhead = cur;
cur = cur->next;
newhead->next = tail;
tail = newhead;
}
*head = newhead;
}
void Reverseshow(pNode head) //逆序打印函数
{
pNode pur = head;
if (pur == NULL)
return;
Reverseshow(pur->next);
printf("%d-->", pur->data);
}
void DelNotTail(pNode pos) //删除无头的非尾节点
{
if (pos == NULL)
return;
if (pos->next == NULL)
free(pos);
else
{
pNode cur = NULL;
pos->data = pos->next->data;
cur = pos->next;
pos->next = cur->next;
free(cur);
}
}
pNode Find(pNode head,Datatype d) //查找函数
{
pNode cur = head;
while (cur!=NULL)
{
if (cur->data == d)
return cur;
cur = cur->next;
}
return NULL;
}
pNode FindMidNode(pNode plist) //查找中间节点函数
{
pNode cur = plist;
pNode fast = plist;
pNode slow = plist;
if (cur == NULL || cur->next == NULL)
return cur;
while (fast->next!=NULL)
{
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
pNode CheckCycle(pNode plist) //判断链表是否带环
{
pNode cur = plist;
pNode fast = plist->next->next;
pNode slow = plist->next;
while (fast->next!=NULL)
{
fast = fast->next->next;
slow = slow->next;
if (fast == slow)
{
return fast;
}
}
return NULL;
}
int GetCircleLength(pNode meet) //测量环的长度
{
pNode cur = meet;
pNode ret = meet->next;
int k = 0;
while (1)
{
k++;
if (cur == ret)
return k;
ret = ret->next;
}
}
pNode GetCircleEntryNode(pNode meet, pNode plist) //查找环的进入点
{
pNode fast = plist;
pNode slow = plist;
int len=GetCircleLength(meet);
while (len)
{
fast = fast->next;
len--;
}
while (fast != slow)
{
fast = fast->next;
slow = slow->next;
}
return slow;
}
pNode GetNode(pNode plist1, pNode plist2,int k) //CheckCross函数的子函数
{
pNode fast = plist1;
pNode slow = plist2;
int len = k;
while (len)
{
fast = fast->next;
len--;
}
while (fast != slow)
{
fast = fast->next;
slow = slow->next;
}
return slow;
}
pNode CheckCross(pNode p1, pNode p2) //判断两条链是否相交,若相交返回交点位置
{
pNode plist1 = p1;
pNode plist2 = p2;
int count1 = 0, count2 = 0;
int k = 0; //两条链的长度差
while (plist1!=NULL)
{
count1++;
plist1 = plist1->next;
}
while (plist2 != NULL)
{
count2++;
plist2 = plist2->next;
}
if (plist1 != plist2)
return NULL;
if ((count1 - count2) > 0)
{
k = count1 - count2;
return GetNode(p1, p2, k);
}
else
{
k = count2 - count1;
return GetNode(p1, p2, k);
}
}
void JosephCycle(pNode plist, int k) //约瑟夫环
{
pNode cur = plist;
while (cur!=cur->next)
{
pNode pur = NULL;
int count = 2;
while (count!=k)
{
count++;
cur = cur->next;
}
pur = cur->next;
cur->next = pur->next;
printf("%d ", pur->data);
free(pur);
cur = cur->next;
}
printf("%d ", cur->data);
}
void DelKNode(pNode plist, int k) //删除倒数第k个节点
{
pNode ret = plist;
pNode fast = plist;
pNode slow = plist;
pNode cur = NULL;
int len = 0;
while (ret!=NULL)
{
ret = ret->next;
len++;
}
if (k == 0)
{
return;
}
k = k%len;
if (k ==0)
{
plist->data = plist->next->data;
cur = plist->next;
plist->next = cur->next;
free(cur);
return;
}
while (fast->next!=NULL)
{
if (k> 0)
{
fast = fast->next;
k--;
}
else
{
fast = fast->next;
slow = slow->next;
}
}
cur = slow->next;
slow->next = cur->next;
free(cur);
}
pNode Merge(pNode plist1, pNode plist2) //合并两条有序链表
{
pNode ret1 = plist1;
pNode ret2 = plist2;
while (plist1->next != NULL)
{
plist1 = plist1->next;
}
plist1->next = ret2;
SortList(ret1);
return ret1;
}
void SortList(pNode head) //排序
{
pNode cur = head;
pNode tail = NULL;
pNode ret = NULL;
if (head == NULL)
return;
while (cur->next!=tail)
{
while (cur->next!= tail)
{
if ((cur->data) > (cur->next->data))
{
Datatype ret = cur->data;
cur->data = cur->next->data;
cur->next->data = ret;
}
cur = cur->next;
ret = cur;
}
tail = ret;
cur = head;
}
}
void Display(pNode head) //显示函数
{
pNode pur = head;
while (pur != NULL)
{
printf("%d-->", pur->data);
pur = pur->next;
}
printf("over\n");
}
void DestroyList(pNode*head) //释放空间函数
{
pNode cur = NULL;
while (*head!=NULL)
{
cur = *head;
*head = cur->next;
free(cur);
}
*head = NULL;
}
测试函数(test.c)
#include"Linklist.h"
void test1()
{
pNode head = NULL; //结构体类型的指针
InitLinkList(&head);
PushBack(&head, 1);
PushBack(&head, 2);
PushBack(&head, 3);
PushBack(&head, 4);
Display(head);
PopBack(&head);
Display(head);
PopBack(&head);
Display(head);
PopBack(&head);
Display(head);
PopBack(&head);
Display(head);
PopBack(&head);
Display(head);
DestroyList(&head);
}
void test2()
{
pNode head = NULL;
InitLinkList(&head);
PushFront(&head,1);
PushFront(&head,2);
PushFront(&head,3);
PushFront(&head,4);
Display(head);
PopFront(&head);
Display(head);
PopFront(&head);
Display(head);
PopFront(&head);
Display(head);
PopFront(&head);
Display(head);
PopFront(&head);
Display(head);
DestroyList(&head);
}
void test3()
{
pNode head = NULL;
InitLinkList(&head);
PushFront(&head, 1);
PushFront(&head, 2);
PushFront(&head, 3);
PushFront(&head, 4);
Display(head);
Insert(&head, 9, 2);
Display(head);
DestroyList(&head);
}
void test4() //逆序
{
pNode head = NULL;
InitLinkList(&head);
PushFront(&head, 1);
PushFront(&head, 2);
PushFront(&head, 3);
PushFront(&head, 4);
PushFront(&head, 5);
PushFront(&head, 6);
Display(head);
Reverse(&head);
Display(head);
DestroyList(&head);
}
test5()
{
pNode head = NULL;
InitLinkList(&head);
PushFront(&head, 1);
PushFront(&head, 2);
PushFront(&head, 3);
PushFront(&head, 4);
PushFront(&head, 5);
Display(head); //显示
Reverseshow(head); //逆序显示
DestroyList(&head);
}
test6()
{
pNode head = NULL;
pNode pos = NULL;
InitLinkList(&head);
PushFront(&head, 1);
PushFront(&head, 2);
PushFront(&head, 3);
PushFront(&head, 4);
PushFront(&head, 5);
Display(head);
pos=Find(head, 2);
if (pos == NULL)
printf("\n");
else
printf("%d\n", pos->data);
DelNotTail(pos);
Display(head);
DestroyList(&head);
}
test7()
{
pNode head = NULL;
InitLinkList(&head);
PushFront(&head, 1);
PushFront(&head, 5);
PushFront(&head, 3);
PushFront(&head, 2);
PushFront(&head, 4);
Display(head);
SortList(head);
Display(head);
DestroyList(&head);
}
void test8()
{
pNode head = NULL;
pNode ret = NULL;
InitLinkList(&head);
PushFront(&head, 1);
PushFront(&head, 5);
PushFront(&head, 3);
PushFront(&head, 2);
PushFront(&head, 4);
Display(head);
ret=FindMidNode(head);
if (ret!=NULL)
printf("%d\n", ret->data);
else
{
printf("\n");
}
DestroyList(&head);
}
void test9()
{
pNode p1 = NULL;
pNode p2 = NULL;
pNode newhead = NULL;
InitLinkList(&p1);
InitLinkList(&p2);
PushBack(&p1, 1);
PushBack(&p1, 3);
PushBack(&p1, 5);
PushBack(&p1, 7);
Display(p1);
PushBack(&p2, 0);
PushBack(&p2, 2);
PushBack(&p2, 4);
PushBack(&p2, 6);
PushBack(&p2, 8);
Display(p2);
newhead=Merge(p1,p2);
Display(newhead);
/*DestroyList(&newhead);*/
}
void test10()
{
pNode p1 = NULL;
PushBack(&p1, 1);
PushBack(&p1, 3);
PushBack(&p1, 5);
PushBack(&p1, 7);
Display(p1);
DelKNode(p1, 12);
Display(p1);
DestroyList(&p1);
}
void test11()
{
pNode ret = NULL;
pNode p1 = NULL;
PushBack(&p1, 1);
PushBack(&p1, 3);
PushBack(&p1, 5);
PushBack(&p1, 7);
PushBack(&p1, 8);
PushBack(&p1, 9);
PushBack(&p1, 10);
Find(p1, 10)->next = Find(p1, 7);
ret = CheckCycle(p1);
if (ret == NULL)
{
printf("no\n");
}
else
printf("yes\n");
}
void test12()
{
pNode pos = NULL;
pNode p1 = NULL;
PushBack(&p1, 1);
PushBack(&p1, 3);
PushBack(&p1, 5);
PushBack(&p1, 7);
PushBack(&p1, 8);
PushBack(&p1, 9);
PushBack(&p1, 10);
Find(p1, 10)->next = Find(p1, 7);
pos = CheckCycle(p1);
int tmp = GetCircleLength(pos);
printf("%d\n", tmp);
}
void test13()
{
pNode pos = NULL;
pNode p1 = NULL;
pNode ret = NULL;
PushBack(&p1, 1);
PushBack(&p1, 3);
PushBack(&p1, 5);
PushBack(&p1, 7);
PushBack(&p1, 8);
PushBack(&p1, 9);
PushBack(&p1, 10);
Find(p1, 10)->next = Find(p1, 3);
pos = CheckCycle(p1);
if (pos == NULL)
{
printf("no\n");
}
else
{
ret=GetCircleEntryNode(pos, p1);
printf("%d\n", ret->data);
}
}
void test14()
{
pNode meet = NULL;
pNode p1 = NULL;
pNode p2 = NULL;
PushBack(&p1, 1);
PushBack(&p1, 3);
PushBack(&p1, 5);
PushBack(&p1, 7);
PushBack(&p1, 8);
PushBack(&p1, 9);
PushBack(&p1, 10);
PushBack(&p2, 2);
PushBack(&p2, 4);
PushBack(&p2, 6);
Find(p2, 6)->next = Find(p1, 7);
meet=CheckCross(p1, p2);
if (meet == NULL)
{
printf("不相交");
}
else
{
printf("相交\n");
printf("%d\n", meet->data);
}
Display(p1);
Display(p2);
}
void test15()
{
pNode p2 = NULL;
pNode p1 = NULL;
for (int i =1; i<=41; i++)
{
PushBack(&p1, i);
}
Find(p1, 41)->next = Find(p1, 1);
p2 = Find(p1, 1);
JosephCycle(p2, 3);
}
int main()
{
//test1(); //尾插、尾删
//test2(); //头插、头删
//test3(); //指定位置插入数据
//test4(); //逆序
//test5(); //测试逆序打印函数
//test6(); //删除无头非为节点
//test7(); //排序
//test8(); //找中间节点
//test9(); //两条有序链的合并,合并之后依然有序
//test10(); //删除倒数第k个节点
//test11(); //判断是否带环
//test12(); //求环的长度
//test13(); //求环的进入点
//test14(); //判断两条链是否相交
test15(); //约瑟夫环
system("pause");
return 0;
}
各种功能都实现了,但是有的比较麻烦,有简单方法的大神们可以留言。