c语言链表程序题库,C语言实现单链表,单链表面试题面试

单链表是学习不可缺少的一个重要模块,在面试中也会出很多的单链表变种问题,今天就把他们汇总宋总结一下

首先来是实现一个简单的单链表:

(在这里,一些简单的实现单链表的操作函数就不备注了)typedef  int DataType;//typedef了一个类型,以后如果想要改变单链表节点内储存数据的类型就可以直接在这里改变

typedef struct SListNode

{

DataType data;           //数据

struct SListNode* next;  //指向下一个节点的指针

}SListNode;

SListNode* BuyNode(DataType x)//创建单链表的节点

{

SListNode* temp;

temp = (SListNode*)malloc(sizeof(SListNode));//为节点开辟一定大小的空间

temp->data = x;

temp->next = NULL;

return temp;

}

void PushBack(SListNode* & pHead, DataType x)

//在单链表末尾插入数据,这时要检查单链表为空和不为空的两种情况,分别处理

{

//1.空

//2.不空

if (pHead == NULL)

{

pHead = BuyNode(x);

}

else

{

SListNode* Tail = pHead;

while (Tail->next != NULL)

{

Tail = Tail->next;

}

Tail->next = BuyNode(x);

}

}

void PopBack(SListNode* & pHead)

//删除单链表末尾的节点

{

//1.空

//2.一个节点

//3.多节点

if (pHead == NULL)

{

printf("The SList is empty\n");

return;

}

else if (pHead->next == NULL)

{

free(pHead);

pHead = NULL;

}

else

{

SListNode* tail = pHead;

SListNode* prev = NULL;

while (tail->next != NULL)

{

prev = tail;

tail = tail->next;

}

free(tail);

prev->next = NULL;

}

}

//在单链表前面插入一个节点

void PushFront(SListNode* & pHead, DataType x)

{

//1.空

//2.不空

if (pHead == NULL)

{

pHead = BuyNode(x);

}

else if (pHead != NULL)

{

SListNode* cur = BuyNode(x);

cur->next = pHead;

pHead = cur;

}

}

//在单链表前面删除一个节点

void PopFront(SListNode* & pHead)

{

if (pHead == NULL)

{

return;

}

else if (pHead->next == NULL)

{

free(pHead);

pHead = NULL;

}

else if (pHead != NULL)

{

SListNode* cur = pHead;

pHead = pHead->next;

free(cur);

cur = NULL;

}

}

//查找节点并返回它

SListNode* Find(SListNode* pHead, DataType x)

{

SListNode* cur = pHead;

while (cur)

{

if (cur->data == x)

{

return cur;

}

cur = cur->next;

}

return NULL;

}

//在指定位置插入一个节点

void Insert(SListNode* pos, DataType x)

{

assert(pos);

SListNode* temp = BuyNode(x);

temp->next = pos->next;

pos->next = temp;

}

//删除指定节点

void Erase(SListNode* pHead,SListNode* pos)

{

assert(pos);

assert(pHead);

if (pHead == pos)

{

pHead = pHead->next;

free(pos);

pos = NULL;

}

SListNode* prev = pHead;

while (prev)

{

if (prev->next == pos)

{

prev->next = pos->next;

free(pos);

pos = NULL;

break;

}

prev = prev->next;

}

}

//队单链表冒泡排序,(只改变单链表结点的数据)

void Bubble(SListNode* pHead)

{

int exange = 0;

if (pHead == NULL || pHead->next == NULL)

{

return;

}

SListNode* prev = pHead;

SListNode* cur = pHead->next;

SListNode* Tail =NULL;while (Tail != pHead)

{

cur = pHead->next;

prev = pHead;

while (cur != Tail)

{

if (prev->data > cur->data)//比较节点信息,如果满足条件就交换它

{

DataType x;

x = cur->data;

cur->data = prev->data;

prev->data = x;

}

prev = cur;

cur = cur->next;//指向下一个节点,实现迭代

}

Tail = prev;//循环结束后prev指向为节点,赋值给Tail

}

}

//删除一个无头单链表的非尾节点,思想就是交换该节点和下一个节点的信息,删除该节点的后一个节点

void DelNonTailNode(SListNode* pos)

{

assert(pos);

assert(pos->next);

SListNode* del = pos->next;

pos->data = del->data;

pos->next = del->next;

free(del);

del = NULL;

}

//在无头单链表的非头节点插入一个节点

void InsertNonTailNode(SListNode* pos,DataType x)

{

assert(pos);

SListNode* cur = BuyNode(pos->data);

SListNode* temp = pos->next;

cur->next = temp;

pos->next = cur;

pos->data = x;

}

//查找单链表的中间节点并只能遍历一次链表(快慢指针)

//快指针走两步满指针走一步,等到快指针走到尾,则慢指针刚好到中间

SListNode* FindMidNode(SListNode* pHead)

{

assert(pHead);

if (pHead->next == NULL)

{

return pHead;

}

else

{

SListNode* slow = pHead;

SListNode* fast = pHead;

//在这里我给出了两种写法,都是正确的

/*while (fast)//快指针不为空,在下面条件判断快指针的下一个节点也不为空

{

if (fast->next)

{

fast = fast->next->next;

}

else

{

break;

}

slow = slow->next;

}*/

while (fast && fast->next)//注意这里的条件是快指针和快指针的下一个节点都不为空

{

slow = slow->next;

fast = fast->next->next;

}

return slow;//返回慢节点,也就是中间节点

}

return NULL;

}

//查找链表的倒数第k个节点,且只能遍历链表一次

//这也是利用快慢指针,快指针先走k步,慢指针走一步,快指针走一步,则两个指针相差k步,当快指针指向空时,慢指针刚好指向倒数第k个节点

SListNode* FindNode(SListNode* pHead, int k)

{

assert(pHead);

assert(k >= 0);

SListNode* slow = pHead;

SListNode* fast = pHead;

//有问题

/*while (fast && fast->next)

{

while (k--)

{

fast = fast->next;

}

fast = fast->next;

slow = slow->next;

}*/

while (fast && --k)

{

fast = fast->next;

if (fast == NULL)

{

return NULL;

}

}

while (fast->next)

{

fast = fast->next;

slow = slow->next;

}

return slow;

}

//从尾到头打印单链表(利用递归实现)

void PrintTailToHead(SListNode* pHead)

{

if (pHead == NULL)

{

return;

}

else

{

PrintTailToHead(pHead->next);

printf("%d ", pHead->data);

}

}

//逆置单链表   很重要,创建新的头节点,把单链表的每个节点摘下来插入它前面,再把它往前挪构成一个新的单链表,返回新链表的头节点

SListNode*  Reverse(SListNode* pHead)

{

SListNode* cur = pHead;

SListNode* newHead = NULL;

while (cur)

{

SListNode* temp = cur;

cur = cur->next;

temp->next = newHead;

newHead = temp;

}

return newHead;

}

//单链表实现约瑟夫环

//运行时先构造环,注意在代码结尾解环

SListNode* JosePhCycle(SListNode* pHead, int m)

{

SListNode* cur = pHead;

while (1)

{

if (cur == NULL)

{

return NULL;

}

else if (cur == cur->next)//只剩一个节点

{

return cur;

}

else

{

int x = m;

while (--x)//指向第m各节点并删除它,循环程序直到只剩一个节点的时候返回它

{

cur = cur->next;

}

SListNode* del = cur->next;

cur->data = del->data;

cur->next = del->next;

free(del);//释放节点并置空

del = NULL;

}

}

}

//合并两个有序链表,合并后依然有序,摘下一个节点,比较大小插入到新链表的尾部,构成一个新的单链表,返回新链表的头节点

SListNode* Meragelist(SListNode* pHead1, SListNode* pHead2)

{

if (pHead1 == NULL)

{

return pHead2;

}

if (pHead2 == NULL)

{

return pHead1;

}

//SListNode* newHead = pHead1->data data ? pHead1:pHead2;

//while (pHead1 == NULL || pHead2 == NULL)

//{

//if (pHead1->data data)

//{

//newHead = pHead1;

//pHead1 = pHead1->next;

//}

//else if (pHead1->data == pHead2->data)

//{

//newHead = pHead1;

//newHead->next = pHead2;

//pHead1 = pHead1->next;

//pHead2 = pHead2->next;

//}

//else

//{

//newHead = pHead2;

//pHead2 = pHead2->next;

//}

//newHead = newHead->next;

//newHead->next = NULL;

//}

//while (pHead1)

//{

//newHead->next = pHead1;

//pHead1 = pHead1->next;

//}

//while (pHead2)

SListNode* newHead = NULL;

SListNode* cur1 = pHead1;

SListNode* cur2 = pHead2;

if (cur1->data data)

{

newHead = cur1;

cur1 = cur1->next;

}

SListNode* Tail = newHead;

while (cur1 && cur2)

{

if (cur1->data data)

{

Tail->next = cur1;

cur1 = cur1->next;

}

else

{

Tail->next = cur2;

cur2 = cur2->next;

}

Tail = Tail->next;

Tail->next = NULL;

}

if (cur1 != NULL)

{

Tail->next = cur1;

}

if (cur2 != NULL)

{

Tail->next = cur2;

}

return newHead;

}

/判断链表是否带环(可以用快慢指针解决),快指针走两步,慢指针走一步,看看是否会相遇,相遇了则是带环,不想与则不带环

bool IsSListCycle(SListNode* pHead)

{

if (pHead == NULL)

{

printf("The SList isempty\n");

return false;

}

SListNode* slow = pHead;

SListNode* fast = pHead;

while (fast && fast->next)

{

fast = fast->next->next;

slow = slow->next;

if (fast == slow)

{

SListNode* cur = slow;

int length = 0;       //环的长度

do

{

slow = slow->next;

length++;

} while (cur != slow);

printf("%d\n", length);

printf("The SList have cycle\n");

return true;

}

}

printf("The SList NO cycle\n");

return false;

}

//环的入口点

SListNode* CycleEntry(SListNode* pHead)

{

if (pHead == NULL)

{

printf("The SList is empty\n");

return NULL;

}

SListNode* slow = pHead;

SListNode* fast = pHead;

while (fast && fast->next)

{

fast = fast->next->next;

slow = slow->next;

if (fast == slow)

{

return slow;

}

}

}

//链表是否相交,若相交,求交点(不带环)指向同一个节点,并不是相同信息的节点

SListNode* IsItersect(SListNode* pHead1,SListNode* pHead2)

{

if (pHead1 == NULL)

{

printf("链表不相交\n");

return pHead2;

}

if (pHead2 == NULL)

{

printf("链表不相交\n");

return pHead1;

}

SListNode* cur1 = pHead1;

SListNode* cur2 = pHead2;

while (cur1 && cur2)

{

if (cur1 == cur2)

{

printf("链表相交,交点为:%d\n", cur1->data);

return cur1;

}

cur1 = cur1->next;

cur2 = cur2 ->next;

}

return NULL;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值