一、链表
一种链式存储的线性表,用一组地址任意的存储单元存储线性表的数据,称一个存储单元为一个结点。
链表的分类:
1、单链表;2、双向链表;3、带头指针链表;4、不带头指针链表;5、循环链表;6、非循环链表
二、单链表:用一组任意的存储单元存放,位置可以使连续的,不连续的,零散的。
结点包含两个域------数据域、指针域。数据域存放数据的值、指针域存放该元素的直接后继的地址,由于该结构只有一个指针域,所以叫做单链表。
单链表的头指针标志着点链表的开始,头指针指向第一个节点的地址,最后一个节点没有直接后继,所以最后一个节点的指针域为空。
#pragma once
typedef size_t DataType;
//单链表的结构定义
typedef struct SListNode //节点的结构类型
{
struct SListNode *_next;
DataType _data;
}SListNode; //linklist 为单链表结构的指针类型
//创建结点
SListNode* CreateSLitNode(DataType x)
{
SListNode* node = (SListNode*)malloc(sizeof(SListNode));
(node)->_data = x;
(node)->_next = NULL;
return node;
}
//尾插
void SListInsertBack(SListNode** ppHead, DataType x)
{
if (*ppHead == NULL)
{
*ppHead = CreateSLitNode(x);
}
else
{
SListNode * cur = *ppHead;
while (cur->_next != NULL)
{
cur = cur->_next;
}
cur->_next = CreateSLitNode(x);
}
}
//头插
void SListInsertFront(SListNode** ppHead, DataType x)
{
if (*ppHead == NULL)
{
*ppHead = CreateSLitNode(x);
}
else
{
SListNode* newNode = CreateSLitNode(x);
newNode->_next = *ppHead;
*ppHead = newNode;
}
}
//尾删
void SListPopBack(SListNode** ppHead)
{
if (*ppHead == NULL)
{
return;
}
else if ((*ppHead)->_next == NULL)
{
free(*ppHead);
*ppHead = NULL;
}
else
{
SListNode* prev = NULL, *cur = *ppHead;
//SListNode* cur = *ppHead;
while (cur->_next)
{
prev = cur;
cur = cur->_next;
}
free(cur);
prev->_next = NULL;
}
}
//头删
void SListPopFront(SListNode** ppHead)
{
assert(*ppHead);
SListNode* next = (*ppHead)->_next;
free(*ppHead);
*ppHead = next;
}
SListNode* FindSListNode(SListNode* head, DataType x)
{
assert(head);
SListNode * cur;
cur = head->_next;
while (cur != NULL)
if (cur->_data != x)
cur = cur->_next;
else
break;
return cur;
}
//打印单链表
void printSList(SListNode* pHead)
{
SListNode* cur = pHead;
while (cur != NULL)
{
cout << cur->_data << "->";
cur = cur->_next;
}
cout << "NULL" << endl;
}
//释放单链表
void DestorySList(SListNode** ppHead)
{
SListNode* cur = *ppHead;
while (cur)
{
SListNode* next = cur->_next;
free(cur);
cur = next;
}
*ppHead = NULL;
}
//从尾到头打印
void printTailToHead(SListNode* head)
{
//正常写法
if (head == NULL)
{
return;
}
else
{
SListNode* tail = NULL;
while (head != tail)
{
SListNode* cur = head;
while (cur->_next != tail)
{
cur = cur->_next;
}
cout << cur->_data << "->";
tail = cur;
}
cout << "NULL" << endl;
}
//递归写法
/*if (head == NULL)
{
return;
}
printTailToHead(head->_next);
cout << head->_data << " ";*/
}
//删除无头单链表的非尾结点(不能遍历链表)
void without_Head_DelSList(SListNode* pos)
{
assert(pos&&pos->_next);
SListNode* next;
next = pos->_next;
pos->_data = next->_data;
pos->_next = next->_next;
free(next);
}
//在无头单链表的一个节点前插入一个结点(不能遍历链表)
void without_Head_Insert(SListNode* pos, DataType x)
{
SListNode *node = CreateSLitNode(pos->_data);
pos->_data = x;
node->_next = pos->_next;
pos->_next = node;
}
//单链表实现约瑟夫环
SListNode* JosephCycle(SListNode* head, int k)
{
assert(head);
//构成环
SListNode* tail = head;
while (tail->_next)
{
tail = tail->_next;
}
tail->_next = head;
SListNode* cur = head;
while (cur->_next != cur)
{
int count = k;
while (--count)
{
cur = cur->_next;
}
without_Head_DelSList(cur);
}
return cur;
}
//逆置单链表
void ReverseSList(SListNode ** head)
{
//原地逆置法
if (*head == NULL || (*head)->_next == NULL)
{
return;
}
SListNode* p1 = *head;
SListNode* p2 = p1->_next;
SListNode* p3 = p2->_next;
while (p2)
{
p2->_next = p1;
p1 = p2;
p2 = p3;
if (p3)
{
p3 = p3->_next;
}
}
(*head)->_next = NULL;
*head = p1;
//头插法
/*SListNode* newHead = NULL;
SListNode* cur = *head;
while (cur)
{
SListNode* tmp = cur;
cur = cur->_next;
tmp->_next = newHead;
newHead = tmp;
}
*head = newHead;*/
}
//单链表实现冒泡排序
void BubbleSortList(SListNode* head)
{
if (head == NULL || head->_next == NULL)
{
return;
}
SListNode* tail = NULL;
SListNode* cur;
SListNode* next;
while (tail != head->_next)
{
cur = head;
next = cur->_next;
while (next != tail)
{
if (cur->_data > next->_data)
{
DataType tmp = cur->_data;
cur->_data = next->_data;
next->_data = tmp;
}
cur = cur->_next;
next = next->_next;
}
tail = cur;
}
}
//合并两个有序链表
SListNode* MergeList(SListNode* list1, SListNode* list2)
{
/*SListNode* newList = NULL;
if (list1 == NULL)
return list2;
if (list2 == NULL)
return list1;
if (list1 == NULL&&list2 == NULL)
return NULL;
if (list1->_data < list2->_data)
{
newList = list1;
list1 = list1->_next;
}
else
{
newList = list2;
list2 = list2->_next;
}
SListNode* cur = newList;
while (list1 && list2)
{
if (list1->_data < list2->_data)
{
cur->_next = list1;
list1 = list1->_next;
}
else
{
cur->_next = list2;
list2 = list2->_next;
}
cur = cur->_next;
}
if (list1)
cur->_next = list1;
if (list2)
cur->_next = list2;
return newList;*/
//递归写法
SListNode* newList = NULL;
if (list1 == NULL)
return list2;
if (list2 == NULL)
return list1;
if (list1 == NULL&&list2 == NULL)
return NULL;
if (list1->_data < list2->_data)
{
newList = list1;
newList->_next = MergeList(list1->_next, list2);
}
else
{
newList = list2;
newList->_next = MergeList(list1, list2->_next);
}
return newList;
}
//查找单链表的中间节点,要求只能遍历一遍链表
SListNode* FindMiddle(SListNode* head)
{
if (head == NULL)
{
return NULL;
}
SListNode* slow = head;
SListNode* fast = head;
while (fast->_next)
{
fast = fast->_next;
slow = slow->_next;
if (fast->_next)
{
fast = fast->_next;
}
}
return slow;
}
//查找单链表的倒数第k个结点,要求只能遍历一遍链表
SListNode* Find_K_Backward(SListNode* head, DataType k)
{
//思路:两个同步指针,第一个走k-1,然后两个同时向后,快指针走完后,倒数第K个就是慢指针
SListNode* fast = head;
for (size_t i = 0; i < k - 1; i++)
{
if (fast->_next != NULL)
{
fast = fast->_next;
}
else
{
return NULL;
}
}
SListNode* slow = head;
while (fast->_next != NULL)
{
fast = fast->_next;
slow = slow->_next;
}
return slow;
}
//判断链表是否带环,求环的长度和入口
SListNode* IsCycle(SListNode* head)
{
SListNode* slow, *fast;
slow = fast = head;
while (fast)
{
fast = fast->_next;
slow = slow->_next;
if (fast)
{
fast = fast->_next;
}
if (fast == slow)
{
return fast;//相遇点
}
}
return NULL;//不是环
}
//求环的入口
SListNode* CycleEnter(SListNode* head, SListNode* meet)
{
while (head != meet)
{
head = head->_next;
meet = meet->_next;
}
return meet;
}
//求环的长度
DataType CycleLength(SListNode* head, SListNode* enter)
{
DataType length = 1;
SListNode* cur = enter;
while (cur->_next != enter)
{
++length;
cur = cur->_next;
}
return length;
}
//复杂链表的复制
typedef struct ComplexNode
{
DataType _data;
ComplexNode* _next;
ComplexNode* _rand;
}ComplexNode;
ComplexNode* CopyList(ComplexNode* list)
{
}
void testSList()
{
SListNode* list = NULL;
SListInsertBack(&list, 1);
SListInsertBack(&list, 3);
SListInsertBack(&list, 2);
SListInsertBack(&list, 4);
SListInsertFront(&list, 6);
SListInsertFront(&list, 5);
SListPopFront(&list);
SListPopFront(&list);
SListPopBack(&list);
/*DestorySList(&list);*/
SListInsertBack(&list, 6);
SListInsertBack(&list, 5);
SListInsertBack(&list, 4);
printSList(list);
SListNode* p = NULL;
p = FindSListNode(list, 3);
without_Head_Insert(p, 33);
printSList(list);
printTailToHead(list);
/*without_Head_DelSList(p);*/
SListNode* JosephNode = NULL;
JosephNode = JosephCycle(list, 4);
cout << "幸存者为:" << JosephNode->_data << endl;
SListNode*newList = NULL;
SListInsertBack(&newList, 9);
SListInsertBack(&newList, 2);
SListInsertBack(&newList, 5);
SListInsertBack(&newList, 10);
SListInsertFront(&newList, 7);
SListInsertFront(&newList, 1);
BubbleSortList(newList);
printSList(newList);
SListNode*list1 = NULL;
SListNode*list2 = NULL;
SListInsertBack(&list1, 1);
SListInsertBack(&list1, 3);
SListInsertBack(&list1, 5);
SListInsertBack(&list1, 7);
SListInsertBack(&list2, 2);
SListInsertBack(&list2, 4);
SListInsertBack(&list2, 6);
SListInsertBack(&list2, 8);
SListInsertBack(&list2, 8);
SListNode* n = NULL;
n = MergeList(list1, list2);
SListNode* backward;
backward = Find_K_Backward(n, 4);
cout << "倒数第4个为" << backward->_data << endl;
printSList(n);
SListNode* middle;
middle = FindMiddle(n);
cout << "中间点是" << middle->_data << endl;
SListNode* Cycle = NULL;
SListNode* pos, *tail;
SListInsertBack(&Cycle, 1);
SListInsertBack(&Cycle, 2);
SListInsertBack(&Cycle, 3);
SListInsertBack(&Cycle, 4);
SListInsertBack(&Cycle, 5);
SListInsertBack(&Cycle, 6);
SListInsertBack(&Cycle, 7);
SListInsertBack(&Cycle, 8);
SListInsertBack(&Cycle, 9);
pos = FindSListNode(Cycle, 5);
//构成环
tail = Cycle;
while (tail->_next)
{
tail = tail->_next;
}
tail->_next = pos;
SListNode* enter, *meet;
meet = IsCycle(Cycle);
cout << "相遇点是" << meet->_data << endl;
enter = CycleEnter(Cycle, meet);
cout << "入口点是" << enter->_data << endl;
cout << "环的长度为" << CycleLength(Cycle, enter) << endl;
}
单链表和顺序表的区别
1、顺序表支持随机访问,单链表不支持。
2、顺序表插入/删除数据效率低,时间复杂度为O(N),单链表插入删除数据效率高,为O(1)
3、顺序表的cpu高速缓存效率高,单链表cpu高速缓存效率低。
二、双向链表:增加一个指针域指向它前一个结点---一般来说都是带头(无数据域)循环双向链表。
//双向链表的结构定义 带头双向循环链表
typedef struct DLinkNode
{
struct DLinkNode *_next;
struct DLinkNode *_prev;
DataType _data;
}DLinkNode;
//创建双向链表结点
DLinkNode* CreateDListNode(DataType x)
{
DLinkNode* node = (DLinkNode*)malloc(sizeof(DLinkNode));
assert(node);
node->_data = x;
node->_prev = NULL;
node->_next = NULL;
return node;
}
//双向链表的初始化
DLinkNode* DListInit()
{
DataType x = 0;
DLinkNode* DList = CreateDListNode(x);
DList->_next = DList;
DList->_prev = DList;
return DList;
}
//打印双向链表
void printDList(DLinkNode* head)
{
if (head == NULL)
{
return;
}
DLinkNode* cur = head->_next;
while (cur != head)
{
cout << cur->_data << "->";
cur = cur->_next;
}
cout << "Head" << endl;
}
//尾插
void DListInsertBack(DLinkNode* head, DataType x)
{
DLinkNode* tail = head->_prev;
DLinkNode* newDNode = CreateDListNode(x);
tail->_next = newDNode;
newDNode->_prev = tail;
newDNode->_next = head;
head->_prev = newDNode;
}
//头插
void DListInsertHead(DLinkNode* head, DataType x)
{
DLinkNode* next = head->_next;
DLinkNode* newDNode = CreateDListNode(x);
newDNode->_next = next;
next->_prev = newDNode;
head->_next = newDNode;
newDNode->_prev = head;
}
//尾删
void DListPopBack(DLinkNode* head)
{
assert(head);
DLinkNode* end = head->_prev;
DLinkNode* prev = end->_prev;
prev->_next = head;
head->_prev = prev;
free(end);
}
//头删
void DListPopFront(DLinkNode* head)
{
assert(head);
DLinkNode* first = head->_next;
DLinkNode* next = first->_next;
next->_prev = head;
head->_next = next;
free(first);
}
//在一个节点前插入
void DListInsert(DLinkNode* pos, DataType x)
{
assert(pos);
DLinkNode* prev = pos->_prev;
DLinkNode* newDNode = CreateDListNode(x);
newDNode->_next = pos;
pos->_prev = newDNode;
newDNode->_prev = prev;
prev->_next = newDNode;
}
//寻找结点
DLinkNode* FindDListNode(DLinkNode* head, DataType x)
{
assert(head);
DLinkNode* cur = head->_next;
while (cur != head)
{
if (cur->_data == x)
{
return cur;
}
cur = cur->_next;
}
return NULL;
}
//删除
void DListPop(DLinkNode* pos)
{
assert(pos);
DLinkNode* next = pos->_next;
DLinkNode* prev = pos->_prev;
prev->_next = next;
next->_prev = prev;
free(pos);
}