经典算法_线性表

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;
}
原文地址:https://www.cnblogs.com/denggelin/p/5709585.html