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\n", getMidNode(head));//用快慢指针快速查找中间结点的值并显示
return 0;
}
LinkNode *create()//创建一个非循环单链表,并将该链表的头结点地址赋给head
{
LinkNode *head = (LinkNode *)malloc(sizeof(LinkNode));
if (!head)
{
printf("创建链表失败,内存分配失败\n");
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("尾部插入失败,内存分配失败\n");
return;
}
else
{
new->data = x;
new->next = NULL;
}
LinkNode *p = head;//第2步,创建指针p,用于移动
if (!p)
{
printf("头指针为空\n");
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("\n");
}
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("\n最后一个结点是%d\n", 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("分配内存失败\n");
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\n");
}
else
{
S->top = S->top + 1;
S->data[S->top] = x;
}
}
DataType Pop(SeqStack *S)//出栈
{
if (StackEmpty(S))//判栈空
{
printf("stack underflow\n");
exit(0);
}
else
{
return S->data[S->top--];
}
}
DataType GetTop(SeqStack *S)//取栈顶元素
{
if (StackEmpty(S))//判栈空
{
printf("stack underflow\n");
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("\n");
}
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("\n");
}
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("\n");
}
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("\n");
}
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\n", 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("\n");
}
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("\n");
}
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("\n");
}
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("\n");
}
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("\n");
}
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("\n");
}
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;
}