-
链表的结构
typedef struct Node
{
DataType data;
struct Node* next;
}Node, *pNode;
-
链表的基本函数
//初始化
void InitLinList(pNode* pn)
{
assert(pn);
*pn = NULL;
}
//创建新的节点
Node* CreatNewNode(DataType d)
{
Node* node = (Node*)malloc(sizeof(Node));
node->data = d;
node->next = NULL;
return node;
}
//打印
void PrintLinList(pNode first)
{
Node* cur = first;
printf("first-->");
while (cur != NULL)
{
printf("%d-->", cur->data);
cur = cur->next;
}
printf("NULL\n");
}
//尾插
void PushBack(pNode* pn, DataType d)
{
assert(pn);
Node* cur = *pn;
Node* newnode = CreatNewNode(d);
//链表为空
if (*pn == NULL)
{
*pn = newnode;
return;
}
//至少有一个数据
while (cur->next != NULL)
{
cur = cur->next;
}
cur->next = newnode;
}
// 查找(顺序查找) 找到了,返回所在结点地址,没有找到返回 NULL
Node* FindLinList(pNode* pn, DataType d)
{
assert(pn);
Node* cur;
for (cur = *pn; cur != NULL; cur = cur->next)
{
if (cur->data == d)
{
return cur;
}
}
return NULL;
}
一、从尾到头打印单链表
-
递归
void TailPrintR(Node* pfirst)
{
if (pfirst == NULL)
{
return;
}
TailPrintR(pfirst->next);
printf("%d ", pfirst->data);
}
- 非递归
void TailPrint(Node* pfirst)
{
Node* cur = pfirst;
Node* last = NULL;
while (last != pfirst)
{
cur = pfirst;
while (cur->next != last)
{
cur = cur->next;
}
printf("%d ", cur->data);
last = cur;
}
}
二、删除一个无头单链表的非尾节点(不能遍历链表)
void RemoveNoHeadNotTail(Node* Del)
{
assert(Del->next != NULL);
Node* next = Del->next;
Del->data = next->data;
Del->next = next->next;
free(next);
}
三、在无头单链表的一个节点前插入一个节点(不能遍历链表)
void BeforeNode(Node* node, DataType d)
{
assert(node);
Node* newnode = (Node*)malloc(sizeof(Node));
newnode->data = node->data;
newnode->next = node->next;
node->data = d;
node->next = newnode;
}
四、单链表实现约瑟夫环
void JosephCircle(Node* first)
{
// 构成环
Node *cur = first;
while (cur->next != NULL)
{
cur = cur->next;
}
cur->next = first;
cur = first;
while (cur->next != cur)
{
cur = cur->next;
Node* Del = cur->next;
cur->next = Del->next;
free(Del);
cur = cur->next;
}
printf("%d\n", cur->data);
}
五、逆置/反转单链表
void Reverse1(Node* first)
{
if (first == NULL || first->next == NULL)
{
return;
}
Node* p1 = first;
Node* p2 = first->next;
Node* p3 = first->next->next;
while (p2 != NULL)
{
p2->next = p1;
p1 = p2;
p2 = p3;
if (p3 != NULL)
{
p3 = p3->next;
}
}
first->next = NULL;
PrintLinList(p1);
}
void Reverse2(Node* first)
{
assert(first);
Node* result = NULL;
Node* cur = first;
Node* node;
while (cur != NULL)
{
node = cur;
cur = cur->next;
node->next = result;
result = node;
}
PrintLinList(result);
}
六、单链表排序(冒泡排序&快速排序)
void BubbleSort(Node* first)
{
assert(first);
Node* tail = NULL;
Node* cur = first;
int flg = 1;//有序
while (cur != tail)
{
while (cur->next != tail)
{
if (cur->data > cur->next->data)
{
DataType tmp = cur->data;
cur->data = cur->next->data;
cur->next->data = tmp;
flg = 0;
}
cur = cur->next;
}
if (flg == 1)
{
return;
}
tail = cur;
cur = first;
}
}
七、合并两个有序单链表,合并后依然有序
void Merge(Node *list1, Node *list2)
{
Node* result = NULL;
Node* tail = NULL; // result这个链表中的最后一个结点
Node* cur1 = list1;
Node* cur2 = list2;
Node* node;
while (cur1->next != NULL&&cur2->next != NULL)
{
if (cur1->data <= cur2->data)
{
node = cur1;//需要插入的节点;
cur1 = cur1->next;
}
else
{
node = cur2;
cur2 = cur2->next;
}
//把找到的node插入result
if (tail == NULL)
{
result = node;
}
else
{
tail->next = node;
}
node->next = NULL;
//node成为最后一个节点;
tail = node;
}
if (cur1->next == NULL)
{
tail->next = cur2;
}
if (cur2->next == NULL)
{
tail->next = cur1;
}
PrintLinList(result);
}
八、查找链表的中间节点,要求只能遍历一次
void FindMidNode(Node* first)
{
Node* fast = first;
Node* slow = first;
while (1)
{
fast = fast->next;
if (fast == NULL)
{
break;
}
fast = fast->next;
if (fast == NULL)
{
break;
}
slow = slow->next;
}
printf("%d\n", slow->data);
}
九、求两个已排序单链表中相同的数据
void UnionSet(Node* last1, Node* last2)
{
Node* cur1 = last1;
Node* cur2 = last2;
while (cur1 != NULL&&cur2 != NULL)
{
if (cur1->data == cur2->data)
{
printf("%d ", cur1->data);
Node* Front1 = cur1;
Node* Front2 = cur2;
cur1 = cur1->next;
cur2 = cur2->next;
//处理重复问题:如:1 1 2 3 1 1 3 4
if (Front1->data == cur1->data&&Front2->data == cur2->data)
{
cur1 = cur1->next;
cur2 = cur2->next;
}
}
else if (cur1->data < cur2->data)
{
cur1 = cur1->next;
}
else
{
cur2 = cur2->next;
}
}
printf("\n");
}
十、查找链表倒数第k个节点,要求只能遍历一遍
void TheLastK(Node* first, int k)
{
assert(first);
assert(k > 0);
Node* forward = first;
Node* backward = first;
Node* Front = first;
//forward先走(k-1)步
while (--k)
{
forward = forward->next;
}
while (forward->next != NULL)
{
Front = backward;
backward = backward->next;
forward = forward->next;
}
//打印倒数第k个
printf("%d\n", backward->data);
//删除倒数第k个
Front->next = backward->next;
free(backward);
PrintLinList(first);
}
十一、判断两个链表是否相交,若相交,求焦点(不带环)
int GetLength(Node* first)
{
int count = 0;
Node* cur = first;
while (cur!=NULL)
{
count++;
cur = cur->next;
}
return count;
}
Node* Intersect(Node* last1, Node* last2)
{
Node* cur1 = last1;
Node* cur2 = last2;
while (cur1->next!=NULL)
{
cur1 = cur1->next;
}
while (cur2->next != NULL)
{
cur2 = cur2->next;
}
if (cur1!=cur2)
{
printf("不相交\n");
return;
}
//一定有焦点
int len1 = GetLength(last1);
int len2 = GetLength(last2);
int lenD = 0;
Node* forward = NULL;
Node* backward = NULL;
if (len1 <= len2)
{
forward = last2;
backward = last1;
lenD = len2 - len1;
}
else
{
forward = last1;
backward = last2;
lenD = len1 - len2;
}
while (lenD--)
{
forward = forward->next;
}
while (forward != backward)
{
forward = forward->next;
backward = backward->next;
}
return forward;
}
十二、判断单链表是否代换?若带环,求环的长度?求环的入口点?
void IsNoCircle(Node* first)
{
Node* fast = first;
Node* slow = first;
while (fast->next!=NULL)
{
fast = fast->next->next;
slow = slow->next;
if (fast==slow)
{
printf("带环\n");
return;
}
}
printf("不带环\n");
}
//带环
int CircleLength(Node* first)
{
Node* fast = first;
Node* slow = first;
fast = fast->next;
slow = slow->next;
int count = 1;
while (fast!=slow)
{
fast = fast->next;
slow = slow->next;
count++;
}
return count;
}
//入口
Node* Entry(Node* first)
{
Node* fast = first;
Node* slow = first;
fast = fast->next;
slow = slow->next;
while (fast!=slow)
{
fast = fast->next;
slow = slow->next;
}
Node* node = first;
while (node!=slow)
{
node = node->next;
slow = slow->next;
}
return node;
}
十三、复杂链表的复制
typedef struct ComplexNode
{
struct ComplexNode* next;
struct ComplexNode* random;
DataType data;
}CN;
CN * CreateNode(int d)
{
CN *node = (CN *)malloc(sizeof(CN));
node->data = d;
node->random = node->next = NULL;
return node;
}
CN* InitComplexList()
{
CN* n1 = CreateNode(1);
CN* n2 = CreateNode(2);
CN* n3 = CreateNode(3);
CN* n4 = CreateNode(4);
n1->next = n2; n2->next = n3; n3->next = n4;
n1->random = n4; n2->random = n1; n3->random = n3;
return n1;
}
void CopyComplexList(CN* list)
{
// 复制链表每个结点,让新的结点跟在老的结点后边
CN* cur = list;
CN* newnode = NULL;
// cur 只遍历老的结点
while (cur != NULL)
{
newnode = CreateNode(cur->data);
newnode->next = cur->next;
cur->next = newnode;
cur = newnode->next;
}
//复制random
cur = list;
while (cur!=NULL)
{
newnode = cur->next;
if (cur->random!=NULL)
{
newnode->random = cur->random->next;
}
cur = newnode->next;
}
cur = list;
CN *Next, *newNext;
CN *result = list->next;
while (cur!=NULL)
{
newnode = cur->next;
Next = newnode->next;
if (Next!=NULL)
{
newNext = Next->next;
}
else
{
newNext = NULL;
}
cur->next = Next;
newnode->next = newNext;
cur = cur->next;
}
printf("复制成功\n");
}