• 经典算法_线性表


    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;
    }
    
  • 相关阅读:
    ABP之动态WebAPI
    ssh下常用操作汇总(good)
    XP下类似%windir% %userprofile% 的变量的说明(转)
    Cannot update paths and switch to branch at the same time(转)
    git branch(转)
    Git提交代码的处理流程(转)
    Android锁定EditText内容和随机生成验证码
    Android L下载
    vi 命令 使用方法
    Openfire开发配置,Openfire源码配置,OpenFire二次开发配置
  • 原文地址:https://www.cnblogs.com/denggelin/p/5709585.html
Copyright © 2020-2023  润新知