目录

  • 链表的增删(不带头结点)
  • 链表相关面试题
    • 合并两个有序链表
    • 单链表原地逆置
    • 找出链表的倒数第四个节点
    • 找出链表的中间节点
    • 判断单链表是否有环
    • 求链表交点
    • 删除有序单链表中重复的元素
    • 链表按奇数、偶数值拆分

链表的增删(不带头结点)

func.h

#include<stdio.h>
#include<string.h> typedef struct node {
int val;
struct node * next;
}Node, *pNode; void listTailInsert(pNode*, pNode*, int);
void listHeadInsert(pNode*, pNode*, int);
void listSortInsert(pNode*, pNode*, int);
void listDeleteNode(pNode*, pNode*, int);
void listPrint(pNode head);

func.c

#include "func.h"

void listTailInsert(pNode *head, pNode *tail, int val)
{
pNode newNode = (pNode)calloc(1, sizeof(Node));
newNode->val = val;
if (NULL == *tail) { //链表为空
*head = newNode;
*tail = newNode;
}
else {
(*tail)->next = newNode;
*tail = newNode;
}
} void listHeadInsert(pNode *head, pNode *tail, int val)
{
pNode newNode = (pNode)calloc(1, sizeof(Node));
newNode->val = val;
if (NULL == *head) {
*head = newNode;
*tail = newNode;
}
else {
newNode->next = *head;
*head = newNode;
}
} void listSortInsert(pNode *head, pNode *tail, int val)
{
pNode newNode = (pNode)calloc(1, sizeof(Node));
newNode->val = val;
pNode pCur, pPre;
pCur = pPre = *head;
if (NULL == *head) {
*head = newNode;
*tail = newNode;
}
else if (pCur->val > val) { //头插
newNode->next = *head;
*head = newNode;
}
else {
while (pCur) { //中间插入
if (val < pCur->val) {
pPre->next = newNode;
newNode->next = pCur;
break;
}
pPre = pCur;
pCur = pCur->next;
}
if (NULL == pCur) { //尾部插入
pPre->next = newNode;
*tail = newNode;
}
}
} void listDeleteNode(pNode *head, pNode *tail, int val)
{
pNode pPre, pCur;
pPre = pCur = *head;
if (pCur == NULL) {
printf("list is empty!\n");
//printf("Delete failed , doesn't find the node!\n");
return;
}
else if (pCur->val == val) { //删除的是头部
*head = pCur->next;
}
else {
while (pCur) {
if (pCur->val == val) {
pPre->next = pCur->next;
break;
}
pPre = pCur;
pCur = pCur->next;
}
if (pCur == *tail) {
*tail = pPre;
}
if (NULL == pCur) {
printf("Don't find the node!\n");
}
} } void listPrint(pNode head)
{
while (head) {
printf("%3d", head->val);
head = head->next;
}
printf("\n");
}

main.c

#include "func.h"

int main() {
printf("please input the key of node:\n");
pNode head = NULL, tail = NULL;
int val;
while (scanf("%d", &val) != EOF) {
//listTailInsert(&head, &tail, val);
//listHeadInsert(&head, &tail, val);
listSortInsert(&head, &tail, val);
}
while (printf("please input delete num:\n"), scanf("%d", &val) != EOF){
listDeleteNode(&head, &tail, val);
listPrint(head);
}
listPrint(head); return 0;
}
链表相关面试题
  • 合并两个有序链表
#include<stdio.h>
#include<string.h> typedef struct node {
int val;
struct node *next;
}Node, *pNode; void listTailInsert(pNode *head, pNode *tail, int val)
{
pNode newNode = (pNode)calloc(1,sizeof(Node));
newNode->val = val;
if (NULL == *tail) { //链表为空
*head = newNode;
*tail = newNode;
}
else {
(*tail)->next = newNode;
*tail = newNode;
}
} pNode head = NULL, tail = NULL; void Union(pNode head1, pNode tail1, pNode head2, pNode tail2, int len1, int len2) {
int i = 0;
while (head1 && head2) {
if (head1->val >= head2->val) {
listTailInsert(&head, &tail, head2->val);
head2 = head2->next;
}
else {
listTailInsert(&head, &tail, head1->val);
head1 = head1->next;
}
}
while (head1) {
listTailInsert(&head, &tail, head1->val);
head1 = head1->next;
}
while (head2) {
listTailInsert(&head, &tail, head2->val);
head2 = head2->next;
}
} void listPrint(pNode head)
{
while (head) {
printf("%3d", head->val);
head = head->next;
}
printf("\n");
} int main() {
int a[5] = { 1,2,7,9,13 };
int b[8] = { 3,4,6,8,9,11,15,19 };
pNode head1, head2, tail1, tail2;
head1 = head2 = tail1 = tail2 = NULL;
for (int i = 0;i < 5;++i) {
listTailInsert(&head1, &tail1, a[i]);
}
for (int i = 0;i < 8;++i) {
listTailInsert(&head2, &tail2, b[i]);
}
printf("两个有序链表:\n");
listPrint(head1);
listPrint(head2); printf("合并后:\n");
Union(head1, tail1, head2, tail2, 5, 8);
listPrint(head);
return 0;
}

  • 单链表原地逆置

    (三指针法:用三个指针分别指向前三个节点,记为A、B、C,第一步让B的next指向A,A的next置为NULL,接着用循环,每次让B的next指向A,并且让三个指针同时往后移一个为止,直到c为NULL为止。)
#include<stdio.h>

typedef struct node {
int val;
struct node *next;
}Node, *pNode; void listTailInsert(pNode *head, pNode *tail, int val)
{
pNode newNode = (pNode)calloc(1, sizeof(Node));
newNode->val = val;
if (NULL == *tail) { //链表为空
*head = newNode;
*tail = newNode;
}
else {
(*tail)->next = newNode;
*tail = newNode;
}
} void listPrint(pNode head)
{
while (head) {
printf("%3d", head->val);
head = head->next;
}
printf("\n");
} pNode* reverse(pNode *head) {
pNode a = *head, b = (*head)->next, c = b->next;
b->next = a;
a->next = NULL;
while (c) {
a = b;
b = c;
c = c->next;
b->next = a;
}
return b;
} int main() {
int a[5] = { 1,9,3,-2,7 };
pNode head, tail;
head = tail = NULL;
for (int i = 0;i < 5;i++) {
listTailInsert(&head, &tail, a[i]);
}
listPrint(head);
pNode t = reverse(&head);
listPrint(t);
return 0;
}

  • 找出链表的倒数第四个节点

    (双指针法,让第一个结点先移动4次,第二个结点再出发)
#include<stdio.h>

typedef struct node {
int val;
struct node *next;
}Node, *pNode; void listTailInsert(pNode *head, pNode *tail, int val)
{
pNode newNode = (pNode)calloc(1, sizeof(Node));
newNode->val = val;
if (NULL == *tail) { //链表为空
*head = newNode;
*tail = newNode;
}
else {
(*tail)->next = newNode;
*tail = newNode;
}
} void listPrint(pNode head)
{
while (head) {
printf("%3d", head->val);
head = head->next;
}
printf("\n");
} int main() {
int a[10] = { 1,9,3,-2,7,99,6,-3,5,0 };
pNode head, tail, last;
head = tail = NULL;
for (int i = 0;i < 10;i++) {
listTailInsert(&head, &tail, a[i]);
}
listPrint(head);
last = head;
for (int i = 0;i < 4;i++) {
head = head->next;
}
while (head) {
head = head->next;
last = last->next;
}
printf("倒数第四个节点的值为%d\n", last->val);
return 0;
}

  • 找出链表的中间节点

    (双指针法:第一个指针每次移动2步,第二个指针每次移动1步)
#include<stdio.h>
#include<string.h> typedef struct node {
int val;
struct node *next;
}Node, *pNode; void listTailInsert(pNode *head, pNode *tail, int val)
{
pNode newNode = (pNode)calloc(1, sizeof(Node));
newNode->val = val;
if (NULL == *tail) { //链表为空
*head = newNode;
*tail = newNode;
}
else {
(*tail)->next = newNode;
*tail = newNode;
}
} void listPrint(pNode head)
{
while (head) {
printf("%3d", head->val);
head = head->next;
}
printf("\n");
} void findMidNode(pNode head) {
pNode t1, t2;
t1 = t2 = head;
while (t2) {
t2 = t2->next;
t2 = t2->next;
t1 = t1->next;
}
printf("中间节点为%d\n", t1->val);
} int main() {
int a[11] = { 1,9,3,-2,7,99,6,-3,5,0,-8 };
pNode head, tail, last;
head = tail = NULL;
for (int i = 0;i < 10;i++) {
listTailInsert(&head, &tail, a[i]);
}
listPrint(head);
findMidNode(head); return 0;
}

  • 判断单链表是否有环

    (双指针法,快指针每次移动2步,慢指针每次移动1步,若有环快指针必定会在一圈内与慢指针相遇)
#include<stdio.h>
#include<string.h> typedef struct node {
int val;
struct node *next;
}Node, *pNode; void listTailInsert(pNode *head, pNode *tail, int val)
{
pNode newNode = (pNode)calloc(1, sizeof(Node));
newNode->val = val;
if (NULL == *tail) { //链表为空
*head = newNode;
*tail = newNode;
}
else {
(*tail)->next = newNode;
*tail = newNode;
}
} void listPrint(pNode head)
{
while (head) {
printf("%3d", head->val);
head = head->next;
}
printf("\n");
} int judge(pNode head) {
pNode slow, fast;
slow = fast = head;
while (fast) {
slow = slow->next;
fast = fast->next;
fast = fast->next;
if (slow == fast) {
printf("有环!\n");
return 0;
}
}
printf("无环!\n");
return 1;
} int main() {
int a[11] = { 1,9,3,-2,7,99,6,-3,5,0,-8 };
int b[11] = { 1,9,3,-2,7,99,6,-3,5,0,-8 };
pNode head, tail;
head = tail = NULL;
for (int i = 0;i < 10;i++) {
listTailInsert(&head, &tail, a[i]);
}
if (judge(head)) { //无环,输出链表
listPrint(head);
} printf("------------------\n");
pNode head2, tail2;
head2 = tail2 = NULL;
for (int i = 0;i < 10;i++) {
listTailInsert(&head2, &tail2, b[i]);
}
tail2->next = head2; //构造环
if (judge(head2)) { //有环不输出
listPrint(head2);
} return 0;
}

  • 求两个链表的相交结点

    (维护两个指针,先让长的链表的头指针往后移,直至和短链表的长度相同,再同时将两个链表的指针比较并后移)
#include<stdio.h>
#include<string.h> typedef struct node {
int val;
struct node *next;
}Node, *pNode; void listTailInsert(pNode *head, pNode *tail, int val)
{
pNode newNode = (pNode)calloc(1, sizeof(Node));
newNode->val = val;
if (NULL == *tail) { //链表为空
*head = newNode;
*tail = newNode;
}
else {
(*tail)->next = newNode;
*tail = newNode;
}
} void listPrint(pNode head)
{
while (head) {
printf("%3d", head->val);
head = head->next;
}
printf("\n");
} void findcommon(pNode head1, pNode head2, int len1, int len2) {
if (len1 > len2) {
while (len1 - len2) {
head1 = head1->next;
--len1;
}
}
else {
while (len2 - len1) {
head2 = head2->next;
--len2;
; }
}
while (head1&&head2) {
if (head1 == head2) {
printf("公共节点是%d\n", head1->val);
return;
}
head1 = head1->next;
head2 = head2->next;
}
printf("无公共节点!\n");
return;
} int main() {
int a[5] = { 1,2,7,9,13 };
int b[10] = { 3,4,6,8,9,11,15,19,9,2 };
int c[5] = { 20,21,22,23,24 };
pNode head1, head2, tail1, tail2;
head1 = head2 = tail1 = tail2 = NULL;
for (int i = 0;i < 5;++i) {
listTailInsert(&head1, &tail1, a[i]);
}
for (int i = 0;i < 10;++i) {
listTailInsert(&head2, &tail2, b[i]);
}
findcommon(head1, head2, 5, 10); pNode head3, tail3;
head3 = tail3 = NULL;
for (int i = 0;i < 5;++i) {
listTailInsert(&head3, &tail3, c[i]);
}
tail1->next = head3;
tail2->next = head3; findcommon(head1, head2, 10, 15); return 0;
}

  • 删除有序单链表中的重复元素

    (双指针)
#include<stdio.h>
#include<string.h> typedef struct node {
int val;
struct node *next;
}Node, *pNode; void listTailInsert(pNode *head, pNode *tail, int val)
{
pNode newNode = (pNode)calloc(1, sizeof(Node));
newNode->val = val;
if (NULL == *tail) {
*head = newNode;
*tail = newNode;
}
else {
(*tail)->next = newNode;
*tail = newNode;
}
} void listPrint(pNode head)
{
while (head) {
printf("%3d", head->val);
head = head->next;
}
printf("\n");
} void DeleteCommon(pNode *head) {
pNode pCur, pPre, pFree;
pPre = *head;
pCur = (*head)->next;
while (pCur) {
if (pCur->val == pPre->val) {
pFree = pCur;
pPre->next = pCur->next;
pCur = pCur->next;
free(pFree);
}
else {
pPre = pCur;
pCur = pCur->next;
}
}
} int main() {
int a[10] = { 1,3,3,5,5,8,9,9,11,11 };
pNode head, tail;
head = tail = NULL;
for (int i = 0;i < 10;i++) {
listTailInsert(&head, &tail, a[i]);
}
listPrint(head);
DeleteCommon(&head);
listPrint(head);
return 0;
}

  • 链表按奇数、偶数值拆分
#include<stdio.h>

typedef struct node
{
int val;
struct node *next;
}Node, *pNode; void InsertTail(pNode *head, pNode *tail, int val) {
pNode newNode = (char*)calloc(1, sizeof(Node));
newNode->val = val;
if (NULL == *tail) {
*head = newNode;
*tail = newNode;
}
else {
(*tail)->next = newNode;
*tail = newNode;
}
} void partition(pNode head, pNode *head1, pNode *tail1, pNode *head2, pNode *tail2) {
while (head) {
int t = head->val;
if (t % 2 == 1) {
InsertTail(head1, tail1, t);
}
else {
InsertTail(head2, tail2, t);
}
head = head->next;
} } void listPrint(pNode head) {
while (head) {
printf("%-3d", head->val);
head = head->next;
}
printf("\n");
} int main() {
int a[9] = { 1,2,3,4,5,6,7,8,9 };
pNode head, tail, head1, tail1, head2, tail2;
head = tail = head1 = tail1 = head2 = tail2 = NULL;
for (int i = 0;i < 9;++i) {
InsertTail(&head, &tail, a[i]);
}
listPrint(head);
partition(head, &head1, &tail1, &head2, &tail2);
listPrint(head1);
listPrint(head2);
return 0;
}

C语言强化——链表(1)的更多相关文章

  1. C语言强化——链表(2)

    目录 链表的应用: 栈 循环队列 C语言实现动态数组 数组实现定长元素个数层次建树 队列实现不定元素个数层次建树 (*) 栈 栈(链表应用) "stack.h" #include ...

  2. C语言之链表

    这两天在复习C语言的知识,为了给下个阶段学习OC做准备,以下的代码的编译运行环境是Xcode5.0版本,写篇博文把昨天复习的C语言有关链表的知识给大家分享一下,以下是小菜自己总结的内容,代码也是按照自 ...

  3. C语言习题 链表建立,插入,删除,输出

    Problem B: C语言习题 链表建立,插入,删除,输出 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 222  Solved: 92 [Subm ...

  4. YTU 2430: C语言习题 链表建立,插入,删除,输出

    2430: C语言习题 链表建立,插入,删除,输出 时间限制: 1 Sec  内存限制: 128 MB 提交: 576  解决: 280 题目描述 编写一个函数creatlink,用来建立一个动态链表 ...

  5. 关于c语言单项链表尾添加

    犹豫了几天,看了很多大牛写的关于c语言链表,感触很多,终于下定决心,把自己对于链表的理解随之附上,可用与否,自行裁夺.由于作者水平有限也是第一次写,不足之处,竭诚希望得到各位大神的批评指正.制作不易, ...

  6. C语言之链表list

    #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <string.h& ...

  7. C语言:链表实现的一个实例

    问题:写一个程序输入你一年看过的所有电影以及每部电影的各种信息(简化问题:每部电影只要求输入片名和评价) 链表实现: #include<stdio.h> #include<stdli ...

  8. C语言单链表实现19个功能完全详解

    谢谢Lee.Kevin分享了这篇文章 最近在复习数据结构,想把数据结构里面涉及的都自己实现一下,完全是用C语言实现的. 自己编写的不是很好,大家可以参考,有错误希望帮忙指正,现在正处于编写阶段,一共将 ...

  9. (转)c语言_链表实例讲解(两个经典例子)

    建立一个学生成绩的线性链表,对其实现插入,删除,输出,最后销毁. #include <stdio.h>#include <stdlib.h> struct grade {    ...

随机推荐

  1. zabbix监控mysql最简单的方法

    该实验基于我的上一篇文章监控第一台主机的基础上 首先,因为水平有限,我选择直接关闭了防火墙和SELinux. 环境: 两台centos7,服务器端IP是192.168.200.128(以下简称主机), ...

  2. python基础(四)——正则表达式

    #!/usr/bin/python # -*- coding: utf-8 -*- import re print(re.match('www', 'www.runoob.com').span()) ...

  3. elasticsearch技术解析与实战(一) 入门和索引

    GET _cat/nodes GET _cat/health GET _cat/shards GET http://10.37.84.124:9200/secisland?pretty { " ...

  4. mino 路径格式的bucket 数据访问

    实施上这个功能很简答,如果官方不支持,我们可以通过基于nginx 的url rewrite 也可以实现 格式说明 如果配置了domain minio 会将 http://mydomain.com/bu ...

  5. SCS Characteristics

    Each SCS is an autonomous web application. For the SCS's domain, all data, the logic to process that ...

  6. Benthos metrcis 说明

    Benthos 按照input, pipeline ,buffer,conditions,ouput 这个几个大类,为我们提供了 方便的分析metrics,支持json 格式同时可以暴露为 stats ...

  7. lch 儿童围棋课堂 初级篇1 ( (李昌镐 著))

    第1章 常用术语 第2章 吃子 第3章 死活:死活题初步 第4章 劫争 第5章 中盘 第6章 官子 第7章 形势判断 第8章 对杀技巧 第9章 手筋 第1章 常用术语 一 镇 在对方棋子上方隔一路落下 ...

  8. 模拟实现strncpy,strncat,strncmp

    1.模拟实现strncpy  <1.>strncpy相比于strcpy增加了size_t参数可以实现最多拷贝的字节数<2.>(size_t不可以超出拷贝存放的内存大小)来保证不 ...

  9. Web API统一异常处理 【转载】

    前面讲了webapi的安全验证和参数安全,不清楚的朋友,可以看看前面的文章,<Web API系列(二)接口安全和参数校验>,本文主要介绍Web API异常结果的处理.作为内部或者是对外提供 ...

  10. js调用.net后台事件,和后台调用前台等方法总结(转帖)

    js调用.net后台事件,和后台调用前台等方法总结 原文来自:http://hi.baidu.com/xiaowei0705/blog/item/4d56163f5e4bf616bba16725.ht ...