1 腾讯面试题:快速找到未知长度单链表的中间节点
写一个完整的程序,实现随机生成20个元素的链表,用快慢指针快速查找中间结点的值并显示。
2 用循环链表模拟约瑟夫问题,把41个人的顺序编号输出。
可以使用数组解决,也可以使用循环链表解决。这里使用循环链表解决。
3 要求实现用户输入一个数使得26个字母的排列发生变化,例如用户输入3,输出结果是DEFGHIJKLMNOPQRSTUVWXYZABC
同时需要支持负数,例如用户输入-3,输出结果是XYZABCDEFGHIJKLMNOPQRSTUVW
4 利用两个栈S1和S2模拟一个队列,如何用栈的运算来实现队列的插入和删除运算?
5 设A和B是两个单链表,其表中元素递增有序。试写一算法将A和归并成一个按元素值递减有序的单链表C,并要求辅助空间为O(1)。
6 写一个算法将单链表中值重复的结点删除,使所得的结果表中各结点值均不相同。
7 假设以带头结点的单链表表示有序表。编写算法,从有序表A中删除所有和有序表B中元素相同的结点。
8 尾插法建表是将新结点插入到当前链表的表尾上,为此必须增加一个尾指针r,使其始终指向当前链表的尾结点。试写出尾插法建表的算法。
9 以ha和hb为头指针的单链表分别表示有序表A和B,本算法判别表A是否包含在表B内,若是,则返回1,否则返回0
10 算法MergeList的功能是归并两个有序链表La和Lb为有序链表Lc
11 直接选择排序算法对链表按升序进行排序
12 删除单链表中数据值最小的结点
13 原地逆转单链表
14 编程把链表(1)变成链表(2)。单向循环链表逆置
1 腾讯面试题:快速找到未知长度单链表的中间节点
写一个完整的程序,实现随机生成20个元素的链表,用快慢指针快速查找中间结点的值并显示。
利用快慢指针原理:设置两个指针*fast,*mid都指向单链表的头结点,其中*fast的移动速度是*mid的2倍。当*fast指向终端结点的时候,*mid正好就在中间了。这也是标尺的思想。
#include <stdio.h> #include <stdlib.h> #include <time.h> typedef struct node//说明一个结构体 { int data; struct node *next; }LinkNode; LinkNode *create();//创建一个非循环单链表,并将该链表的头结点地址赋给head void add(LinkNode *head, int x);//尾部插入 void print2(LinkNode *head);//遍历,非递归 int getMidNode(LinkNode *head);//用快慢指针快速查找中间结点的值并显示 int main() { time_t ts; srand((unsigned int)time(&ts)); int i = 0; int num = 0;//插入值 LinkNode *head = NULL;//头指针 head = create();//创建一个非循环单链表,并将该链表的头结点地址赋给head for (i = 0; i < 20; i++) { num = rand() % 100 + 1; add(head, num);//尾部插入 } print2(head);//遍历,非递归 printf("中间结点的值是%d ", getMidNode(head));//用快慢指针快速查找中间结点的值并显示 return 0; } LinkNode *create()//创建一个非循环单链表,并将该链表的头结点地址赋给head { LinkNode *head = (LinkNode *)malloc(sizeof(LinkNode)); if (!head) { printf("创建链表失败,内存分配失败 "); return NULL; } else { head->next = NULL; return head; } } void add(LinkNode *head, int x)//尾部插入 { LinkNode *new = (LinkNode *)malloc(sizeof(LinkNode));//第1步,创建指针new,用于存储新数据 if (!new) { printf("尾部插入失败,内存分配失败 "); return; } else { new->data = x; new->next = NULL; } LinkNode *p = head;//第2步,创建指针p,用于移动 if (!p) { printf("头指针为空 "); return; } else { while (p->next)//遍历 { p = p->next; } p->next = new;//第3步,指针p指向指针new } } void print2(LinkNode *head)//遍历,非递归 { LinkNode *p = head; while (p->next) { printf("%d ", p->next->data); p = p->next; } printf(" "); } int getMidNode(LinkNode *head)//用快慢指针快速查找中间结点的值并显示 { LinkNode *fast = head;//快指针 LinkNode *mid = head;//一般指针 while (fast->next)//当fast下一个的结点不为空 { if (fast->next->next)//如果fast下一个的下一个的结点不为空 { fast = fast->next->next;//fast移动两个结点 } else//如果fast下一个的下一个的结点为空 { fast = fast->next;//fast移动一个结点 } mid = mid->next;//mid移动一个结点 } return mid->data;//返回 }
2 用循环链表模拟约瑟夫问题,把41个人的顺序编号输出。
可以使用数组解决,也可以使用循环链表解决。这里使用循环链表解决。
#include <stdio.h> #include <stdlib.h> typedef struct node { int data; struct node *next; }LinkNode; LinkNode *create(int n);//创建循环链表,没有头结点,没有头指针,只有尾指针 int main() { int n = 41;//总人数 int m = 3;//报数周期 int i;//循环 LinkNode *p = create(n);//创建循环链表,没有头结点,没有头指针,只有尾指针,指针p指向第一结点 LinkNode *q; m %= n;//m==3 while (p != p->next)//当p不是只有一个结点的链表的时候 { for (i = 1; i < m - 1; i++)//便于m的修改 { p = p->next;//指针p指向报数的前一个结点 } printf("%d->", p->next->data);//打印报数的结点 q = p->next;//指针q指向报数的结点 p->next = q->next;//跳过报数的结点 free(q);//删除结点 p = p->next;//指针p移动 } printf(" 最后一个结点是%d ", p->data);//最后一个结点 return 0; } LinkNode *create(int n)//创建循环链表,没有头结点,没有头指针,只有尾指针 { LinkNode *head = (LinkNode *)malloc(sizeof(LinkNode)); LinkNode *p = head; LinkNode *new = NULL; int i = 0;//循环 for (i = 1; i <= n; i++) { new = (LinkNode *)malloc(sizeof(LinkNode)); new->data = i; p->next = new; p = new; } new->next = head->next;//最后的结点指针指向第一个结点,形成循环链表 free(head);//删除头指针 return new->next;//返回第一个结点 }
3 要求实现用户输入一个数使得26个字母的排列发生变化,例如用户输入3,输出结果是DEFGHIJKLMNOPQRSTUVWXYZABC
同时需要支持负数,例如用户输入-3,输出结果是XYZABCDEFGHIJKLMNOPQRSTUVW
#include <stdio.h> #include <stdlib.h> typedef char DataType; typedef struct dlnode//双向链表 { DataType data; struct dlnode *prior, *next; }DLNode; DLNode *initNode();//创建双向链表,带有头结点 void print(DLNode *head, int num);//根据num打印链表 int main() { DLNode *head = initNode();//创建双向链表,带有头结点 int num = -3; print(head, num);//根据num打印链表 system("pause"); return 0; } DLNode *initNode()//创建双向链表,带有头结点 { DLNode *head = (DLNode *)malloc(sizeof(DLNode)); if (!head) { printf("分配内存失败 "); return NULL; } else { head->next = head->prior = NULL; DLNode *p = head;//指针p存储前面的结点 DLNode *s = NULL; int i = 0; for (i = 0; i < 26; i++) { s = (DLNode *)malloc(sizeof(DLNode));//存储新结点,指针s存储后面的结点 s->data = 'A' + i; s->prior = p;//s的前趋指向p s->next = p->next; p->next = s;//p的后趋指向s p = s;//指针p变成s } p->next = head->next;//形成循环链表 head->next->prior = p;//形成循环链表 return head; } } void print(DLNode * head, int num)//根据num打印链表 { DLNode * p = head->next;//p指向头结点的下一个结点,即是结点A int i; num %= 26; if (num >= 0) { for (i = 0; i < num; i++) { p = p->next; } } else { while (num) { p = p->prior; num++; } } for (i = 0; i < 26; i++) { printf("%c ", p->data); p = p->next; } }
4 利用两个栈S1和S2模拟一个队列,如何用栈的运算来实现队列的插入和删除运算?
#include <stdio.h> #include <stdlib.h> typedef int DataType; #define StackSize 100 typedef struct { DataType data[StackSize]; int top; }SeqStack; void InitStack(SeqStack *S);//置空栈 int StackEmpty(SeqStack *S);//判栈空 int StackFull(SeqStack *S);//判栈满 void Push(SeqStack *S, DataType x);//入栈 DataType Pop(SeqStack *S);//出栈 DataType GetTop(SeqStack *S);//取栈顶元素 void InitQueue(SeqStack *S1, SeqStack *S2);//置空队列 int QueueEmpty(SeqStack *S1, SeqStack *S2);//判队空 int QueueFull(SeqStack *S1, SeqStack *S2);//判队满,未实现 void EnQueue(SeqStack *S1, SeqStack *S2, DataType x);//入队列 DataType GetFront(SeqStack *S1, SeqStack *S2);//取队头元素,未实现 DataType DeQueue(SeqStack *S1, SeqStack *S2);//出队列 int main() { SeqStack S1, S2;//利用两个栈S1和S2模拟一个队列 InitQueue(&S1, &S2);//置空队列 int i = 0; for (i = 0; i < 10; i++) { EnQueue(&S1, &S2, i);//入队列 } for (i = 0; i < 5; i++) { printf("%d ", DeQueue(&S1, &S2));//出队列 } return 0; } void InitStack(SeqStack *S)//置空栈 { S->top = -1; } int StackEmpty(SeqStack *S)//判栈空 { return S->top == -1; } int StackFull(SeqStack *S)//判栈满 { return S->top == StackSize - 1; } void Push(SeqStack *S, DataType x)//入栈 { if (StackFull(S))//判栈满 { printf("stack overflow "); } else { S->top = S->top + 1; S->data[S->top] = x; } } DataType Pop(SeqStack *S)//出栈 { if (StackEmpty(S))//判栈空 { printf("stack underflow "); exit(0); } else { return S->data[S->top--]; } } DataType GetTop(SeqStack *S)//取栈顶元素 { if (StackEmpty(S))//判栈空 { printf("stack underflow "); exit(0); } else { return S->data[S->top]; } } void InitQueue(SeqStack *S1, SeqStack *S2)//置空队列 { InitStack(S1);//置空栈 InitStack(S2); } int QueueEmpty(SeqStack *S1, SeqStack *S2)//判队空 { return StackEmpty(S1) && StackEmpty(S2);//判栈空 } int QueueFull(SeqStack *S1, SeqStack *S2)//判队满,未实现 { } void EnQueue(SeqStack *S1, SeqStack *S2, DataType x)//入队列 { Push(S1, x);//入栈 } DataType GetFront(SeqStack *S1, SeqStack *S2)//取队头元素,未实现 { } DataType DeQueue(SeqStack *S1, SeqStack *S2)//出队列 { if (QueueEmpty(S1, S2))//S1空S2空 { printf("queue empty"); exit(0); } else if (!StackEmpty(S1) && StackEmpty(S2))//S1不空S2空 { while (!StackEmpty(S1))//判栈空 { Push(S2, Pop(S1));//入栈 } return Pop(S2);//出栈 } else { return Pop(S2);//出栈 } }
5 设A和B是两个单链表,其表中元素递增有序。试写一算法将A和归并成一个按元素值递减有序的单链表C,并要求辅助空间为O(1)。
#include <stdio.h> #include <stdlib.h> typedef int DataType; typedef struct linknode { DataType data; struct linknode *next; }LinkNode; LinkNode *create();//创建头结点 void add(LinkNode *head, DataType x);//尾部插入 void print(LinkNode *head);//打印 LinkNode *mergeSort(LinkNode *A, LinkNode *B);//归并两个带头结点的递增有序表为一个带头结点递减有序表 int main() { LinkNode *La = create();//创建头结点 LinkNode *Lb = create(); add(La, 1);//尾部插入 add(La, 2); add(La, 9); add(Lb, 3); add(Lb, 6); add(Lb, 9); add(Lb, 998); print(La);//打印 print(Lb); LinkNode *C = mergeSort(La, Lb);//归并两个带头结点的递增有序表为一个带头结点递减有序表 print(C); return 0; } LinkNode *create()//创建头结点 { LinkNode *head = (LinkNode *)malloc(sizeof(LinkNode)); head->next = NULL; return head; } void add(LinkNode *head, DataType x)//尾部插入 { LinkNode *p = head; LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode)); s->data = x; s->next = NULL; while (p->next) { p = p->next; } p->next = s; } void print(LinkNode *head)//打印 { if (!head) { return; } LinkNode *p = head; while (p->next) { printf("%d ", p->next->data); p = p->next; } printf(" "); } LinkNode *mergeSort(LinkNode *A, LinkNode *B)//归并两个带头结点的递增有序表为一个带头结点递减有序表 { LinkNode *pa, *pb, *q, *C; pa = A->next;//pa指向A表开始结点 pb = B->next;//pb指向B表开始结点 C = A; C->next = NULL;//取A表的表头建立空的C表 free(B);//回收B表的头结点空间 while (pa && pb) { if ((pa->data) < (pb->data)) { q = pa; pa = pa->next; } else if ((pa->data) > (pb->data)) { q = pb; pb = pb->next; } else { q = pa; pa = pa->next; pb = pb->next; } q->next = C->next; C->next = q;//将摘下的结点q作为开始结点插入C表 } while (pa)//若pa表非空,则处理pa表 { q = pa; pa = pa->next; q->next = C->next; C->next = q; } while (pb)//若pb表非空,则处理pb表 { q = pb; pb = pb->next; q->next = C->next; C->next = q; } return C; }
6 写一个算法将单链表中值重复的结点删除,使所得的结果表中各结点值均不相同。
#include <stdio.h> #include <stdlib.h> typedef int DataType; typedef struct linknode { DataType data; struct linknode *next; }LinkNode; LinkNode *create();//创建头结点 void add(LinkNode *head, DataType x);//尾部插入 void print(LinkNode *head);//打印 void deleteList(LinkNode *head);//将单链表中值重复的结点删除,使所得的结果表中各结点值均不相同 int main() { LinkNode *head = create();//创建头结点 add(head, 1);//尾部插入 add(head, 2); add(head, 3); add(head, 4); add(head, 1);//尾部插入 add(head, 2); add(head, 3); add(head, 4); add(head, 4);//尾部插入 add(head, 3); add(head, 2); add(head, 1); print(head);//打印 deleteList(head); print(head); return 0; } LinkNode *create()//创建头结点 { LinkNode *head = (LinkNode *)malloc(sizeof(LinkNode)); head->next = NULL; return head; } void add(LinkNode *head, DataType x)//尾部插入 { LinkNode *p = head; LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode)); s->data = x; s->next = NULL; while (p->next) { p = p->next; } p->next = s; } void print(LinkNode *head)//打印 { if (!head) { return; } LinkNode *p = head; while (p->next) { printf("%d ", p->next->data); p = p->next; } printf(" "); } void deleteList(LinkNode *head)//将单链表中值重复的结点删除,使所得的结果表中各结点值均不相同 { LinkNode *p, *q, *s; p = head->next; while (p && p->next) { q = p;//由于要做删除操作,所以q指针指向要删除元素的直接前趋 while (q->next) { if (p->data == q->next->data)//删除与*p的值相同的结点 { s = q->next; q->next = s->next; free(s); } else { q = q->next; } } p = p->next; } }
7 假设以带头结点的单链表表示有序表。编写算法,从有序表A中删除所有和有序表B中元素相同的结点。
#include <stdio.h> #include <stdlib.h> typedef int DataType; typedef struct node { DataType data; struct node *next; }LinkNode; LinkNode *create();//创建头结点 void add(LinkNode *head, DataType x);//尾部插入 void print(LinkNode *head);//打印 void deleteListAB(LinkNode *headA, LinkNode *headB);//从有序表A中删除所有和有序表B中元素相同的结点 int main() { LinkNode *headA = create();//创建头结点 LinkNode *headB = create(); add(headA, 1);//尾部插入 add(headA, 2); add(headA, 3); add(headA, 4); add(headB, 1);//尾部插入 add(headB, 4); print(headA);//打印 print(headB); deleteListAB(headA, headB);//从有序表A中删除所有和有序表B中元素相同的结点 print(headA);//打印 return 0; } LinkNode *create()//创建头结点 { LinkNode *head = (LinkNode *)malloc(sizeof(LinkNode)); head->next = NULL; return head; } void add(LinkNode *head, DataType x)//尾部插入 { LinkNode *p = head; LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode)); s->data = x; s->next = NULL; while (p->next) { p = p->next; } p->next = s; } void print(LinkNode *head)//打印 { if (!head) { return; } LinkNode *p = head; while (p->next) { printf("%d ", p->next->data); p = p->next; } printf(" "); } void deleteListAB(LinkNode *headA, LinkNode *headB)//从有序表A中删除所有和有序表B中元素相同的结点 {//headA和headB分别是指向有序链表A和B的头指针 LinkNode *p, *q, *r;//声明三个LinkNode类型指针 p = headA;//p指向表A的头结点 q = headB->next;//q指向表B的第一个结点 while (p->next && q)//当p不是尾结点且q不是尾指针(空指针) { if ((p->next->data) < (q->data))//如果p结点的后继结点的值小于q结点的值,p指向下一结点 { p = p->next; } else { if ((p->next->data) == (q->data))//如果p结点的后继结点的值等于q结点的值 { r = p->next;//r指向p结点的后继结点 p->next = r->next;//改变p结点的指针,使其指向r结点的后继结点,也就是让p指向了p的后继的后继结点 free(r);//释放r结点,也就删除了表A中与表B中值相同的结点 } q = q->next;//如果p结点的后继结点的值大于或等于q结点的值(则已做过删除),q指针后移 } } }
8 尾插法建表是将新结点插入到当前链表的表尾上,为此必须增加一个尾指针r,使其始终指向当前链表的尾结点。试写出尾插法建表的算法。
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> typedef int DataType; typedef struct node//结点类型定义 { DataType data;//结点数据域 struct node *next;//结点指针域 }ListNode; ListNode *createListR();//尾插法建立带头结点的单链表算法 void print(ListNode *head);//打印 int main() { ListNode *head = createListR();//尾插法建立带头结点的单链表算法 print(head);//打印 return 0; } ListNode *createListR()//尾插法建立带头结点的单链表算法 { ListNode *head = (ListNode *)malloc(sizeof(ListNode));//申请头结点 ListNode *p, *r; DataType x; r = head;//尾指针初始指向头结点 scanf("%d", &x); while (x != 0) { p = (ListNode *)malloc(sizeof(ListNode));//申请新结点 p->data = x; r->next = p;//新结点连接到尾结点之后 r = p;//尾指针指向新结点 scanf("%d", &x); } r->next = NULL;//终端结点指针域置空 return head; } void print(ListNode *head)//打印 { ListNode *p = head; while (p->next) { printf("%d ", p->next->data); p = p->next; } printf(" "); }
9 以ha和hb为头指针的单链表分别表示有序表A和B,本算法判别表A是否包含在表B内,若是,则返回1,否则返回0
#include <stdio.h> #include <stdlib.h> typedef int DataType; typedef struct node { DataType data; struct node *next; }LinkNode; LinkNode *create();//创建头结点 void add(LinkNode *head, DataType x);//尾部插入 void print(LinkNode *head);//打印 int inclusion(LinkNode *ha, LinkNode *hb);//以ha和hb为头指针的单链表分别表示有序表A和B,本算法判别表A是否包含在表B内,若是,则返回1,否则返回0 int main() { LinkNode *headA = create();//创建头结点 LinkNode *headB = create(); add(headA, 2);//尾部插入 add(headA, 3); add(headB, 1);//尾部插入 add(headB, 2); add(headB, 3); add(headB, 4); print(headA);//打印 print(headB); printf("%d ", inclusion(headA, headB));//以ha和hb为头指针的单链表分别表示有序表A和B,本算法判别表A是否包含在表B内,若是,则返回1,否则返回0 return 0; } LinkNode *create()//创建头结点 { LinkNode *head = (LinkNode *)malloc(sizeof(LinkNode)); head->next = NULL; return head; } void add(LinkNode *head, DataType x)//尾部插入 { LinkNode *p = head; LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode)); s->data = x; s->next = NULL; while (p->next) { p = p->next; } p->next = s; } void print(LinkNode *head)//打印 { if (!head) { return; } LinkNode *p = head; while (p->next) { printf("%d ", p->next->data); p = p->next; } printf(" "); } int inclusion(LinkNode *ha, LinkNode *hb)//以ha和hb为头指针的单链表分别表示有序表A和B,本算法判别表A是否包含在表B内,若是,则返回1,否则返回0 { LinkNode *pa, *pb; pa = ha->next; pb = hb->next; if (!pa) { return 1; } while ((pb) && ((pa->data) >= (pb->data))) { if ((pa->data) == (pb->data)) { return inclusion(pa, pb);//递归 } else { pb = pb->next; } } return 0; }
10 算法MergeList的功能是归并两个有序链表La和Lb为有序链表Lc
#include <stdio.h> #include <stdlib.h> typedef int DataType; typedef struct node { DataType data; struct node *next; }LinkNode; LinkNode *create();//创建头结点 void add(LinkNode *head, DataType x);//尾部插入 void print(LinkNode *head);//打印 LinkNode *mergeList(LinkNode *La, LinkNode *Lb);//算法MergeList的功能是归并两个有序链表La和Lb为有序链表Lc int main() { LinkNode *La = create();//创建头结点 LinkNode *Lb = create(); add(La, 1);//尾部插入 add(La, 2); add(La, 9); add(Lb, 3); add(Lb, 9); add(Lb, 99); add(Lb, 998); print(La);//打印 print(Lb); LinkNode *C = mergeList(La, Lb);//算法MergeList的功能是归并两个有序链表La和Lb为有序链表Lc print(C); return 0; } LinkNode *create()//创建头结点 { LinkNode *head = (LinkNode *)malloc(sizeof(LinkNode)); head->next = NULL; return head; } void add(LinkNode *head, DataType x)//尾部插入 { LinkNode *p = head; LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode)); s->data = x; s->next = NULL; while (p->next) { p = p->next; } p->next = s; } void print(LinkNode *head)//打印 { if (!head) { return; } LinkNode *p = head; while (p->next) { printf("%d ", p->next->data); p = p->next; } printf(" "); } LinkNode *mergeList(LinkNode *La, LinkNode *Lb)//算法MergeList的功能是归并两个有序链表La和Lb为有序链表Lc { LinkNode *pa, *pb, *pc; LinkNode *Lc; pa = La->next;//pa和pb分别指向两个链表的开始结点 pb = Lb->next; Lc = pc = La;//用La的头结点作为Lc的头结点 while (pa && pb) { if ((pa->data) < (pb->data)) { pc->next = pa; pc = pa; pa = pa->next; } else if ((pa->data) == (pb->data)) { pc->next = pa; pc = pa; pa = pa->next; pb = pb->next; } else { pc->next = pb; pc = pb; pb = pb->next; } } if (pa)//插入链表剩余部分 { pc->next = pa; } else { pc->next = pb; } free(Lb);//释放Lb的头结点 return Lc;//返回合并后的表 }
11 直接选择排序算法对链表按升序进行排序
#include <stdio.h> #include <stdlib.h> typedef int DataType; typedef struct node { DataType data; struct node *next; }ListNode; ListNode *create();//创建头结点 void add(ListNode *head, DataType x);//尾部插入 void print(ListNode *head);//打印 void selectSort(ListNode *head);//直接选择排序算法对链表按升序进行排序 int main() { ListNode *head = create();//创建头结点 add(head, 7);//尾部插入 add(head, 9); add(head, 4); add(head, 3); print(head);//打印 selectSort(head);//直接选择排序算法对链表按升序进行排序 print(head);//打印 return 0; } ListNode *create()//创建头结点 { ListNode *head = (ListNode *)malloc(sizeof(ListNode)); head->next = NULL; return head; } void add(ListNode *head, DataType x)//尾部插入 { ListNode *p = head; ListNode *s = (ListNode *)malloc(sizeof(ListNode)); s->data = x; s->next = NULL; while (p->next) { p = p->next; } p->next = s; } void print(ListNode *head)//打印 { if (!head) { return; } ListNode *p = head; while (p->next) { printf("%d ", p->next->data); p = p->next; } printf(" "); } void selectSort(ListNode *head)//直接选择排序算法对链表按升序进行排序 { ListNode *p, *min, *r; DataType temp; p = head->next; while (p) { min = p;//每次假设第一个为最小值 r = p->next;//指针r用于移动 while (r) { if ((min->data) > (r->data)) { min = r; } r = r->next; } temp = min->data; min->data = p->data; p->data = temp; p = p->next; } }
12 删除单链表中数据值最小的结点
#include <stdio.h> #include <stdlib.h> typedef int DataType; typedef struct node { DataType data; struct node *next; }ListNode; ListNode *create();//创建头结点 void add(ListNode *head, DataType x);//尾部插入 void print(ListNode *head);//打印 void deleteMin(ListNode *head);//删除单链表中数据值最小的结点 int main() { ListNode *head = create();//创建头结点 add(head, 7);//尾部插入 add(head, 9); add(head, 3); add(head, 6); print(head);//打印 deleteMin(head);//删除单链表中数据值最小的结点 print(head);//打印 return 0; } ListNode *create()//创建头结点 { ListNode *head = (ListNode *)malloc(sizeof(ListNode)); head->next = NULL; return head; } void add(ListNode *head, DataType x)//尾部插入 { ListNode *p = head; ListNode *s = (ListNode *)malloc(sizeof(ListNode)); s->data = x; s->next = NULL; while (p->next) { p = p->next; } p->next = s; } void print(ListNode *head)//打印 { if (!head) { return; } ListNode *p = head; while (p->next) { printf("%d ", p->next->data); p = p->next; } printf(" "); } void deleteMin(ListNode *head)//删除单链表中数据值最小的结点 { ListNode *p, *minPre;//指针minPre指示数据值最小的结点之前的结点 if (!head->next)//单链表为空表 { return; } minPre = head; p = head->next; while (p->next)//查找数据值最小的结点 { if ((minPre->next->data) > (p->next->data)) { minPre = p; } p = p->next; } p = minPre->next; minPre->next = p->next; free(p); }
13 原地逆转单链表
#include <stdio.h> #include <stdlib.h> typedef int DataType; typedef struct node { int data; struct node *next; }ListNode; ListNode *create();//初始化链表 void add(ListNode *head, DataType x);//链表的插入 void print(ListNode *head);//打印 ListNode *invertList(ListNode *head);//原地逆转单链表 int main() { ListNode *head = create();//初始化链表 add(head, 1);//链表的插入 add(head, 2); add(head, 3); print(head);//打印 head = invertList(head);//原地逆转单链表 print(head);//打印 return 0; } ListNode *create()//初始化链表 { ListNode *head = (ListNode *)malloc(sizeof(ListNode)); head->next = NULL; return head; } void add(ListNode *head, DataType x)//链表的插入 { if (!head) { return; } ListNode *s = (ListNode *)malloc(sizeof(ListNode)); s->data = x; s->next = NULL; ListNode *p = head; while (p->next) { p = p->next; } p->next = s; } void print(ListNode *head)//打印 { ListNode *p = head; while (p->next) { printf("%d ", p->next->data); p = p->next; } printf(" "); } ListNode *invertList(ListNode *head)//原地逆转单链表 { if (!head->next || !head->next->next)//如果为空结点或者只有一个结点,没有必要逆转 { exit(0); } ListNode *p, *q; p = head->next;//p指向待反序链表的第一个结点 head->next = NULL; while (p) { q = p;//q指向待处理链表中的第一个结点 p = p->next;////p指向待处理链表的下一个结点 q->next = head->next;//将q所指结点插入到链头 head->next = q; } return head; }
14 编程把链表(1)变成链表(2)。单向循环链表逆置
#include <stdio.h> #include <stdlib.h> typedef int DataType; typedef struct linknode { DataType data; struct linknode *next; }LinkNode; LinkNode *create();//创建头结点 void add(LinkNode *head, DataType x);//尾部插入 void print(LinkNode *head);//打印 LinkNode *listConverts(LinkNode *head);//单向循环链表逆置 int main() { LinkNode *head = create();//创建头结点 add(head, 1);//尾部插入 add(head, 2); add(head, 3); add(head, 4); print(head);//打印 head = listConverts(head);//单向循环链表逆置 print(head); return 0; } LinkNode *create()//创建头结点 { LinkNode *head = (LinkNode *)malloc(sizeof(LinkNode)); head->next = head; return head; } void add(LinkNode *head, DataType x)//尾部插入 { LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode)); s->data = x; s->next = NULL; LinkNode *p = head; while (p->next != head) { p = p->next; } p->next = s; s->next = head; } void print(LinkNode *head)//打印 { LinkNode *p = head; while (p->next != head) { printf("%d ", p->next->data); p = p->next; } printf(" "); } LinkNode *listConverts(LinkNode *head)//单向循环链表逆置 { if (head->next == head || head->next->next == head)//如果为空结点或者只有一个结点,没有必要逆转 { exit(0); } LinkNode *p, *q; p = head->next;//p指向待反序链表的第一个结点 head->next = head; while (p != head) { q = p;//q指向待处理链表中的第一个结点 p = p->next;////p指向待处理链表的下一个结点 q->next = head->next;//将q所指结点插入到链头 head->next = q; } return head; }