目录

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

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

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. Project Euler 54

    #include<bits/stdc++.h> using namespace std; ]; ]; ; map<char,int> mp; //map<char,cha ...

  2. struts2的国际化i18n

    先来例子,普通的读取配置文件中不同语言信息,一个测试类,一份中文配置文件,一份英文配置文件 中文配置文件,书写中文“欢迎”,myelipse自动转码 public class Readi18n { p ...

  3. ls -l 和du 的区别

    编程之路刚刚开始,错误难免,希望大家能够指出. 简单的来说,ls -l 显示的是实际文件(目录)大小,而du显示的是文件(目录)占用磁盘空间的大小. linux下一切皆文件. 首先,硬盘的最小存储单位 ...

  4. File file = new File("路径名") 路径名的2种写法

    项目的结构:相同颜色是同级的 bean的配置文件的读取和一般文件的读取有点差别的 public static void getValue(String key){ //传入"time&quo ...

  5. php 页面调转导致session丢失解决方法

    例如在a页面设置了会话,然后打印会话值,可以成功打印,但是调转到b页面后,会话丢失了. 原因有不少,一个原因就是没有在页面开头加入session_start();当然你也可以直接配置php.ini文件 ...

  6. [转]DB2错误代码大全

    DB2 SQLSTATE 消息 异常 一2008-03-31 13:17SQLSTATE 消息本节列示 SQLSTATE 及其含义.SQLSTATE 是按类代码进行分组的:对于子代码,请参阅相应的表. ...

  7. LOJ 2736 「JOISC 2016 Day 3」回转寿司 ——堆+分块思路

    题目:https://loj.ac/problem/2736 如果每个询问都是 l = 1 , r = n ,那么每次输出序列的 n 个数与本次操作的数的最大值即可.可以用堆维护. 不同区间的询问,可 ...

  8. java自动装箱的一个例子

    Object obj = 56; int i = (Integer)obj; 第一行等价于: Object obj = Integer.valueOf(56);      Integer.valueO ...

  9. HttpServletResponse和HttpServletRequest

    1.相关的接口   HttpServletRequest HttpServletRequest接口最常用的方法就是获得请求中的参数,这些参数一般是客户端表单中的数据.同时,HttpServletReq ...

  10. hadoop大数据基础框架技术详解

    一.什么是大数据 进入本世纪以来,尤其是2010年之后,随着互联网特别是移动互联网的发展,数据的增长呈爆炸趋势,已经很难估计全世界的电子设备中存储的数据到底有多少,描述数据系统的数据量的计量单位从MB ...