您的位置:首页 > 编程语言 > C语言/C++

C语言实现单链表以及链表对应的面试题

2017-03-24 23:52 441 查看
//List.h
#define _CRT_SECURE_NO_WARNINGS 1
#ifndef __LIST_H__
#define __LIST_H__

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

typedef int DataType;
typedef struct Node
{
DataType data;
struct Node* next;
}Node,*pNode,*pList;

void InitList(pList* pplist); //初始化
void PushBack(pList* pplist, DataType d); //尾插
void PushFront(pList* pplist, DataType d);//头插
void PopBack(pList* pplist);//尾删
void PopFront(pList* pplist);//头删
void show(pList plist);//输出
int GetListLength(pList plist);//求链表的长度
pNode Find(pList plist, DataType d);//查找
void Remove(pList* pplist, DataType d);//删除第一个出现的d
void RemoveAll(pList* pplist, DataType d);//删除链表所有d
void Insert(pList*pplist, pNode pos, DataType d);//在节点前插入元素
void Erase(pList* pplist, pNode pos);// 删除当前节点
void DestroyList(pList *pplist);//销毁链表

//链表面试题
void EraseNotTail(pNode pos);  //删除一个无头非尾节点
void InsertFrontNode(pNode pos, DataType d);  //在一个无头单链表的非头结点前插入一个元素
void Reverselist(pList *pplist);    //将单链表逆序
pList Merge(pList L1, pList L2);    //合并两个有序链表
pList Merge2(pList L1, pList L2);    //合并两个有序链表
pNode FindMidNode(pList list);        //查找链表中间节点
void DelkNode(pList* pplist, int k);  //删除链表倒数第k的元素
pNode JosephCycle(pList *pplist, int sum);   //约瑟夫环问题
pNode CheckCycle(pList plist);    //检查是否带环
int GetCycleLength(pNode meet);   //求环的长度
pNode GetCycleEntryNode(pList plist, pNode meetNode);  //求环的入口地址
void PrintReversely(pList plist);  //逆序打印单链表
int CheckCross(pList list1, pList list2); //检查两个单链表是否相交

#endif


//List.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"List.h"
void InitList(pList* pplist)
{
assert(pplist);
*pplist = NULL;
}
pNode BuyNode(DataType d)
{
pNode pnode = (pNode)malloc(sizeof(Node));
if (pnode == NULL)
{
perror("malloc");
return NULL;
}
pnode->data = d;
pnode->next = NULL;
return pnode;
}
void PushBack(pList* pplist, DataType d)
{
assert(pplist);
pNode NewNode = BuyNode(d);
if (*pplist == NULL)  //无节点
{
*pplist = NewNode;
}
else  //有节点
{
pNode cur = *pplist;
while (cur->next)
{
cur = cur->next;
}
cur->next = NewNode;
}
}
void PushFront(pList* pplist, DataType d)
{
assert(pplist);
pNode NewNode = BuyNode(d);
if (*pplist == NULL)//无节点
{
*pplist = NewNode;
}
else//有节点
{
NewNode->next = *pplist;
*pplist = NewNode;
}
}
void PopBack(pList* pplist)
{
pNode cur = *pplist;
pNode del = NULL;
assert(pplist);
if (*pplist == NULL)//无节点
{
printf("链表为空\n");
return;
}
else if (cur->next==NULL) //有一个节点
{
free(cur);
*pplist = NULL;
}
else //多个节点
{
while (cur->next)  //找倒数第二个元素
{
del = cur;
cur=cur->next;
}
free(cur);
del->next = NULL;
}
}
void PopFront(pList* pplist)
{
pNode cur = *pplist;
assert(pplist);
if (*pplist == NULL)//无节点
{
printf("链表为空\n");
return;
}
else if (cur->next == NULL)//有一个节点
{
free(cur);
*pplist = NULL;
}
else//多个节点
{
*pplist = cur->next;
free(cur);
}
}
void show(pList plist)
{
if (plist == NULL)
{
printf("链表为空\n");
return;
}
pNode cur = plist;
printf("list:");
while (cur)
{
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL\n");
}

int GetListLength(pList plist)
{
pNode cur = plist;
int count = 0;
while (cur)
{
cur = cur->next;
count++;
}
return count;
}

pNode Find(pList plist, DataType d)
{
pNode cur = plist;
while (cur)
{
if (cur->data == d)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
void Remove(pList* pplist, DataType d)  //删除第一个出现的d
{
assert(pplist);
pNode cur = *pplist;
pNode del = NULL;
while (cur)
{
if (cur->data == d)
{
if (*pplist == cur)
{
*pplist = cur->next;//要删除的是第一个节点
}
else
{
del->next = cur->next;//cur的上一个指向下一个
}
free(cur);
return;//这里必须结束不然下面del=cur;程序就会崩溃
}
del = cur; //作用保存cur上一个元素的地址
cur = cur->next;
}
}
void RemoveAll(pList* pplist, DataType d)//删除链表的所有d元素
{
assert(pplist);
pNode cur = *pplist;
pNode tmp= NULL;
pNode del = NULL;
while (cur)
{
tmp = cur;//保存cur的地址
if (cur->data == d)
{
if (*pplist == cur)
{
*pplist = cur->next;//要删除的是第一个节点
}
else
{
del->next = cur->next;
}
cur = del;//删除后让cur保存cur上一个元素的地址
free(tmp);
}
del = cur;//作用保存cur上一个元素的地址
cur = cur->next;
}
}
void Insert(pList*pplist, pNode pos, DataType d)
{
assert(*pplist);
assert(pos);
pNode NewNode = BuyNode(d);
pNode cur = *pplist;
if (pos == cur)  //头节点
{
NewNode->next = *pplist;
*pplist = NewNode;
}
else
{
while (cur->next!=pos)//找到pos前一个节点
{
cur = cur->next;
}
NewNode->next = pos;
cur->next = NewNode;
}

}

void Erase(pList* pplist, pNode pos)
{
assert(pplist);
assert(pos);
pNode cur = *pplist;
pNode del = NULL;
//if (cur == NULL)
//{
//  printf("链表为空无法删除\n");
//  return;
//}
//if (cur == pos)  //头结点
//{
//  *pplist = cur->next;
//  free(cur);
//}
//else
//{
//  while (cur->next!=pos)
//  {
//      cur = cur->next;
//  }
//  cur->next = pos->next;
//  free(pos);
//}
if (pos->next == NULL)
{
PopBack(pplist);
return NULL;
}
pos->data = pos->next->data;//相当于删除下个元素把下一个元素的值给pos
del = pos->next;//del保存下个元素的地址
pos->next = pos->next->next;
free(del);
}
void DestroyList(pList *pplist)
{
pNode cur = *pplist;
while (cur)
{
pNode del = cur;
cur = cur->next;
free(del);
}
*pplist = NULL;
}
void EraseNotTail(pNode pos) //删除一个无头非尾节点
{
assert(pos->next);
pNode cur = pos->next;
pos->data = pos->next->data;
pos ->next = pos->next->next;
free(cur);
}
void InsertFrontNode(pNode pos, DataType d) //在一个无头单链表的非头结点前插入一个元素
{
pNode NewNode = BuyNode(d);
DataType tmp = 0;
NewNode->next = pos->next;//将元素插入pos后边
pos->next = NewNode;
tmp = pos->data; //然后将pos的值和d相交换
pos->data = NewNode->data;
NewNode->data = tmp;
}
void Reverselist(pList *pplist) //将单链表逆序
{
assert(pplist);
pNode cur = *pplist;
pNode tmp = NULL;
pList NewList = NULL;
while (cur)
{
tmp = cur;
cur = cur->next;
tmp->next = NewList;
NewList = tmp;
}
*pplist = NewList;
}

pList Merge(pList L1, pList L2)    //合并两个有序链表
{
pList NewList = NULL;
pNode tail = NULL;
if (L1 == L2)//如果两个相等返回任意一个
{
return L1;
}
if (L1 == NULL)//一个为空 返回另一个
{
return L2;
}
if (L2 == NULL)
{
return L1;
}
if (L1->data <= L2->data) //头结点
{
NewList = L1;
L1 = L1->next;
}
else
{
NewList = L2;
L2 = L2->next;
}
tail = NewList;
while (L1&&L2)
{
if (L1->data <= L2->data)
{
tail->next = L1;
tail = L1;
L1 = L1->next;
}
else
{
tail->next = L2;
tail = L2;
L2 = L2->next;
}
}
if (L1 == NULL)
{
tail->next = L2;
}
if (L2 == NULL)
{
tail->n
11fae
ext = L1;
}
return NewList;
}
pList Merge2(pList L1, pList L2)    //合并两个有序链表采用递归调用
{
pList NewList = NULL;
if (L1 == L2)
{
return L1;
}
if (L1 == NULL)
{
return L2;
}
if (L2 == NULL)
{
return L1;
}
if (L1->data <= L2->data)
{
NewList = L1;
NewList->next = Merge2(L1->next, L2);
}
else
{
NewList = L2;
NewList->next = Merge2(L2->next, L1);
}
return NewList;
}

pNode FindMidNode(pList list)        //查找链表中间节点
{
pNode fast = list; //快指针
pNode slow = list;  //慢指针
while (fast&&fast->next)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
void DelkNode(pList* pplist, int k)  //删除链表倒数第k的元素
{
assert(pplist);
pNode fast = *pplist;//快指针
pNode slow = *pplist; //慢指针
while (fast)
{
k--;
if (k < 0)
{
slow = slow->next;
}
fast = fast->next; //让快指针多走k步
}//然后当快指针下一个为空时慢指针刚好指向倒数第k的元素
pNode cur = slow->next;
slow->data = cur->data;
slow->next = cur->next;
free(cur);
}

pNode JosephCycle(pList *pplist, int sum)   //约瑟夫环问题
{
assert(pplist);
int i = 0;
pNode cur = *pplist;
while ((cur->next) != cur)
{
if (cur->next == cur)
{
break;
}
for (i = 0; i < sum-1; i++)
{
cur = cur->next;
}
printf("%d ", cur->data);
pNode del = cur->next;
cur->data = cur->next->data;
cur->next = cur->next->next;
free(del);
}
return cur;
}

pNode CheckCycle(pList plist)    //检查是否带环
{
pNode fast = plist;
pNode slow = plist;
while (fast&&fast->next)
{
fast = fast->next->next;//快指针走两步
slow = slow->next;//慢指针走一步
if (fast == slow)
{
return slow;// 当快慢相遇就返回这个元素地址
}
}
return NULL;
}
int GetCycleLength(pNode meet)   //求环的长度
{
int count = 0;
pNode cur = meet;
do
{
cur = cur->next;
++count;
} while (cur != meet);
return count;
}
pNode GetCycleEntryNode(pList plist, pNode meetNode) //求环的入口地址
{
pNode cur = plist;
while (cur != meetNode)
{
cur = cur->next;
meetNode = meetNode->next;
}
return cur;
}
void PrintReversely(pList plist)  //逆序打印单链表
{
pNode cur = plist;
if (plist == NULL)
{
return ;
}
if (cur != NULL)  //递归调用
{
PrintReversely(cur->next);
}
printf("%d ", cur->data);
}

int CheckCross(pList list1, pList list2) //检查两个单链表是否相交
{
pNode cur1 = list1;
pNode cur2 = list2;
if (cur1==NULL||cur2==NULL)
{
return 0;
}
while (cur1)
{
cur1 = cur1->next;
}
while (cur2)
{
cur2 = cur2->next;
}
if (cur1 == cur2)
return 1;
return 0;
}


Test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"List.h"
//测试尾插以及尾删
void test1()
{
pList list = NULL;
InitList(&list);
PushBack(&list, 2);
PushBack(&list, 4);
PushBack(&list, 5);
PushBack(&list, 7);
PopBack(&list);
PopBack(&list);
PopBack(&list);
PopBack(&list);
PopBack(&list);

}
//测试头插以及头删
void test2()
{
pList list = NULL;
InitList(&list);
PushFront(&list, 1);
PushFront(&list, 2);
PushFront(&list, 3);
PushFront(&list, 4);
PushFront(&list, 5);
PopFront(&list);
PopFront(&list);
PopFront(&list);
PopFront(&list);
PopFront(&list);
PopFront(&list);

}
//测试输出以及链表长度
void test3()
{
pList list = NULL;
InitList(&list);
PushFront(&list, 1);
PushFront(&list, 2);
PushFront(&list, 3);
PushFront(&list, 4);
PushFront(&list, 5);
int ret = GetListLength(list);
printf("%d\n", ret);
show(list);
}

//测试Remove RemoveAll
void test4()
{
pList list = NULL;
InitList(&list);
PushBack(&list, 2);
PushBack(&list, 4);
PushBack(&list, 5);
PushBack(&list, 8);
PushBack(&list, 5);
PushBack(&list, 5);
PushBack(&list, 7);
PushBack(&list, 6);
show(list);
Remove(&list, 5);
show(list);
RemoveAll(&list, 5);
show(list);

}
//测试合并两个有序链表
void TestMerge()
{
pList list = NULL;
pList List = NULL;
pList NewList = NULL;
InitList(&list);
InitList(&List);
InitList(&NewList);
PushBack(&list, 2);
PushBack(&list, 4);
PushBack(&list, 5);
PushBack(&list, 7);

PushBack(&List, 1);
PushBack(&List, 3);
PushBack(&List, 5);
PushBack(&List, 8);

show(list);
show(List);
NewList = Merge2(list, List);
show(NewList);
pNode cur = NULL;
cur = FindMidNode(NewList);
printf("%d", cur->data);

}
//测试约瑟夫环问题
void TestJosephCycle()
{
pList list = NULL;
InitList(&list);
PushBack(&list, 1);
PushBack(&list, 2);
PushBack(&list, 3);
PushBack(&list, 4);
PushBack(&list, 5);
Find(list, 5)->next = Find(list, 1);
pNode ret=JosephCycle(&list, 3);
printf("%d\n", ret->data);
}
//测试链表长度
void TestGetCycleLength()
{
pList list = NULL;
InitList(&list);
PushBack(&list, 1);
PushBack(&list, 2);
PushBack(&list, 3);
PushBack(&list, 4);
PushBack(&list, 5);
Find(list, 5)->next = Find(list, 1);
pNode ret = CheckCycle(list);
int tmp = GetCycleLength(ret);
printf("%d\n", tmp);
}
//测试检查是否带环
void TestCheckCycle()
{
pList list = NULL;
InitList(&list);
PushBack(&list, 1);
PushBack(&list, 2);
PushBack(&list, 3);
PushBack(&list, 4);
PushBack(&list, 5);
//Find(list, 5)->next = Find(list, 3);
pNode ret = CheckCycle(list);
if (ret == NULL)
{
printf("不带环\n");
}
else
{
printf("%d\n", ret->data);
}
}
//测试环的入口地址
void TestGetCycleEntryNode()
{
pList list = NULL;
InitList(&list);
PushBack(&list, 1);
PushBack(&list, 2);
PushBack(&list, 3);
PushBack(&list, 4);
PushBack(&list, 5);
PushBack(&list, 6);
PushBack(&list, 7);
PushBack(&list, 8);
Find(list, 8)->next = Find(list, 3);
pNode ret = CheckCycle(list);
pNode tmp = GetCycleEntryNode(list, ret);
printf("%d\n", tmp->data);

}
//测试逆序打印单链表
void TestPrintReversely()
{
pList list = NULL;
InitList(&list);
PushBack(&list, 1);
PushBack(&list, 2);
PushBack(&list, 3);
PushBack(&list, 4);
PushBack(&list, 5);
PrintReversely(list);

}
//测试两个单链表是否相交
void TestCheckCross()
{
pList list = NULL;
pList List = NULL;
InitList(&list);
InitList(&List);
PushBack(&list, 2);
PushBack(&list, 4);
PushBack(&list, 5);
PushBack(&list, 7);

PushBack(&List, 1);
PushBack(&List, 3);
PushBack(&List, 5);
PushBack(&List, 8);
Find(List, 8)->next = Find(list, 5);
show(list);
show(List);
int ret = CheckCross(list, List);
if (ret == 1)
{
printf("相交\n");
}
if (ret == 0)
{
printf("不相交\n");
}
}

int main()
{
//test1();
//test2();
//test3();
test4();
//TestMerge();
//TestList();
//TestJosephCycle();
//TestCheckCycle();
//TestGetCycleLength();
//TestGetCycleEntryNode();
//TestCheckCross();
//TestPrintReversely();
//TestComplexList();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c语言 面试题 链表