数据结构与算法

数据结构与算法

1. 数据结构引入

在这里插入图片描述

2. 线性表之顺序表

2.1 什么是线性表及顺序表

在这里插入图片描述
在这里插入图片描述

2.2 代码规范要求

注意代码分层
在这里插入图片描述

2.3 顺序表的实现1

在这里插入图片描述
在这里插入图片描述

2.4 顺序表的实现2

sqlist-create()函数:
last :表示最后一个有效数据元素的下标,last=-1 表示一个空值
数组的每个元素要清零
在这里插入图片描述
检查拼写错误:gcc *.c

2.5 顺序表的实现

顺序表的插入:
在这里插入图片描述

2.6 顺序表的实现4

线性表的删除与合并、将重复的删除
在这里插入图片描述
合并:
在这里插入图片描述

2.7 顺序表的实现5

顺序表的删除:
在这里插入图片描述

2.8 顺序表的结尾

在这里插入图片描述
sqlist.h

/*typedef int data_t; //有分号,在编译的时候就做处理
#define N 129   //不用写分号,在预处理的时候展开

struct sqlist_t {
	data_t data[N];
	int last;
	}
typedef struct sqlist_t sqlist; //sqlist L; struct sqlist_t L;
typedef struct sqlist_t *sqlink; // struct sqlist_t *p; sqlink p;


typedef struct {
	data_t data[N];
	int last;
}sqlist, *sqlink;
*/


typedef int data_t; //有分号,在编译的时候就做处理
#define N 129   //不用写分号,在预处理的时候展开

/*
struct sqlist_t {
	data_t data[N];
	int last;
}
*/

typedef struct {
	data_t data[N];
	int last;
}sqlist, *sqlink;

sqlink list_create();
int list_clear(sqlink L);
int list_free(sqlink L);
int list_empty(sqlink L);
int list_length(sqlink L);
int list_locate(sqlink L, data_t value);
int list_insert(sqlink L, data_t value, int pos);
int list_delete(sqlink L, int pos);
int list_merge(sqlink L1, sqlink L2);
int list_purge(sqlink L);
int list_show(sqlink L);

sqlist.c


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"sqlist.h"

sqlink list_create(){
	//malloc
	sqlink L;
	L = (sqlink)malloc(sizeof(sqlist)); //申请的结构体,用结构体的指针进行存储
			//,强制类型转换
	if(L == NULL){
		printf("list malloc failed\n");
		return L;
	}
	
	//malloc申请的内存堆上不进行处理,值不确定,需要赋值,0或\0
	//initialize
	memset(L, 0, sizeof(sqlist));
	L->last = -1; //空值,结构体的指针访问结构体的成员


	//return 
	return L;

}

/*
 * @ret 0-success -1-failed
 **/
int list_clear(sqlink L)
{
	if(L == NULL)  //空表
		return -1;

	memset(L, 0, sizeof(sqlist));
	L->last = -1; //空值,结构体的指针访问结构体的成员
	return 0;
}

int list_free(sqlink L){
	if (L == NULL)
		return -1;
	free(L);
	L = NULL;
	return 0;
}



/*
 * List_empty: Is list empty?
 * para L: list
 * @ret 1--empty  0--not empty
 */

int list_empty(sqlink L){
	if(L->last == -1)
		return 1;
	else
		return 0;
}

int list_length(sqlink L){
	if(L == NULL)
		return -1;
	return(L->last+1);
}


/*
 * @ret -1--not exist pos
 * */
int list_locate(sqlink L, data_t value){
	int i;
	for(i = 0; i <= L->last; i++){
		if(L->data[i] == value)
			return 1;
	}

	return -1;
}


int list_insert(sqlink L, data_t value, int pos){
	//full
	int i;
	if(L->last == N-1){
		printf("list is full\n");
		return -1;
	}

	//check para 0<=pos<=last+1 [0, last+1]
	if(pos < 0 || pos > L->last+1) {
		printf("pos is invalid\n");
		return -1;
	}

	//move
	for(i = L->last; i >= pos; i--)	{
		L->data[i+1] = L->data[i];
	}

	//update value last
	L->data[pos] = value;
	L->last++;

	return 0;
}
	

int list_delete(sqlink L, int pos)
{
	int i;
	if(L->last == -1) {
		printf("list is empty\n");
		return -1;
	}
	
	//pos[0, last]
	if(pos < 0 || pos > L->last) {
		printf("delete pos is invalid\n");
		return -1;
	}

	//move[pos+1,last]
	for(i = pos+1; i <= L->last; i++){
		L->data[i-1] = L->data[i];
	}

	//update
	L->last--;

	return 0;

}
int list_merge(sqlink L1, sqlink L2)
{
	int i = 0;
	int ret;

	while(i <= L2->last){
	ret = list_locate(L1, L2->data[i]);
	if(ret == -1){
		if(list_insert(L1, L2->data[i], L1->last+1) == -1)
			return -1;
	}
	i++;
	}
	return 0;
}


int list_purge(sqlink L)
{
	int i;
	int j;

	if(L->last == 0)
		return 0;
	
	i = 1;
	while(i <= L->last) {
		j = i-1;
		while(j >= 0){
			if(L->data[i] == L->data[j]){
				list_delete(L,i);
				break;
			}else {
			j--;
			}
		}
	  // if(j < 0) {
		i++;
	//	}
	}	
	return 0;
}

int list_show(sqlink L) {
	int i;
	if(L == NULL) //无效的线性表
		return -1;
	if(L->last == -1)
		printf("list is empty\n");

	for(i = 0; i <= L->last; i++) {
		printf("%d ", L->data[i]);
	}
	puts("");
	return 0;
}

test.c

#include<stdio.h>
#include"sqlist.h"

void test_insert();
void test_delete();
void test_merge();
void test_purge();

int main(int argc, const char *argv[])
{
//	test_insert();
//	test_delete();
//	test_merge();
	test_purge();
	return 0;

}

void test_insert(){

	sqlink L;
	L = list_create();
	if(L == NULL)
		return ;

	list_insert(L, 1, 0);
	list_insert(L, 1, 0);
	list_insert(L, 1, 0);
	list_insert(L, 2, 0);
	list_insert(L, 3, 0);
	list_insert(L, 4, 0);
	list_insert(L, 4, 0);
	list_insert(L, 5, 0);
	list_insert(L, 6, 0);
	list_insert(L, 7, 0);
	list_show(L);
	list_free(L);

}

void test_delete(){

	sqlink L;
	L = list_create();
	if(L == NULL)
		return ;

	list_insert(L, 1, 0);
	list_insert(L, 1, 0);
	list_insert(L, 1, 0);
	list_insert(L, 2, 0);
	list_insert(L, 3, 0);
	list_insert(L, 4, 0);
	list_insert(L, 4, 0);
	list_insert(L, 5, 0);
	list_insert(L, 6, 0);
	list_insert(L, 7, 0);

	list_show(L);

	list_delete(L,0);
	list_show(L);

	list_free(L);
}

void test_merge(){
	sqlink L1;
	L1 = list_create();
	if(L1 == NULL)
		return;
	
	
	sqlink L2;
	L2 = list_create();
	if(L2 == NULL)
		return;

	list_insert(L1, 1, 0);
	list_insert(L1, 1, 0);
	list_insert(L1, 1, 0);
	list_insert(L1, 2, 0);
	list_insert(L1, 3, 0);
	list_insert(L1, 4, 0);
	list_insert(L1, 4, 0);
	list_insert(L1, 5, 0);
	list_insert(L1, 6, 0);

	list_insert(L2, 7, 0);
	list_insert(L2, 9, 0);
	list_insert(L2, 6, 0);

	list_show(L1);
	list_show(L2);
	printf("***********************\n");
	list_merge(L1,L2);
	list_show(L1);
	list_show(L2);
}

void test_purge(){
	sqlink L;
	L = list_create();
	if(L == NULL)
		return ;

	list_insert(L, 1, 0);
	list_insert(L, 1, 0);
	list_insert(L, 1, 0);
	list_insert(L, 2, 0);
	list_insert(L, 3, 0);
	list_insert(L, 4, 0);
	list_insert(L, 4, 0);
	list_insert(L, 5, 0);
	list_insert(L, 6, 0);
	list_insert(L, 7, 0);
	list_show(L);
	list_purge(L);
	list_show(L);
}

3. 线性表之链表

3.1 什么是链表及原理

在这里插入图片描述
在这里插入图片描述
指针类型由后继数据类型来决定。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

放栈上的话A在一个函数当中,函数结束,A就销毁了。
将结点放到堆上,利用动态内存,用户输入一个数,就申请一个内存空间,再输入,再申请。

什么时候加点?什么时候用箭头?->什么时候用栈,什么时候用堆
在这里插入图片描述在这里插入图片描述

3.2 单链表的实现-创建

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
malloc返回的是void的指针,需要进行强制转换

H = (linklist)malloc(sizeof(listnode))

3.3 单链表的实现-尾部插入和遍历

在这里插入图片描述
在这里插入图片描述

3.4 单链表的实现-按位置插入

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4. 线性表之链表应用

4.1 单链表实现-链表删除

在这里插入图片描述

4.2 单链表实现-链表释放

在这里插入图片描述
在这里插入图片描述

5. 单链表的操作实现

5.1 链表的反转

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.2 链表求相邻两个结点最大值

在这里插入图片描述
在这里插入图片描述

5.3 有序链表合并

在这里插入图片描述

在这里插入图片描述
linklist.h


typedef int data_t;
typedef struct node{
	data_t data;
	struct node*next;
}listnode, *linklist;

linklist list_create();
int list_tail_insert(linklist H, data_t value);

linklist list_get(linklist H, int pos);
int list_insert(linklist H, data_t value, int pos);
int list_delete(linklist H, int pos);
int list_show(linklist H);
int list_reverse(linklist H);
linklist  list_adjmax(linklist H, data_t *value);
int list_merge(linklist H1, linklist H2);
linklist list_free(linklist H);

linklist.c

#include<stdio.h>
#include<stdlib.h>
#include"linklist.h"

linklist list_create(){
	linklist H;
	
	//节点放堆上
	H = (linklist)malloc(sizeof(listnode));
	if(H == NULL){   //内存申请失败
		printf("malloc failed\n");
		return H;
	}

	//赋初值
	H->data = 0;
	H->next = NULL; //头结点next为空

	return H;
}

int list_tail_insert(linklist H, data_t value)
{
	linklist p;
	linklist q;
	//1 new node p
	if ((p = (linklist)malloc(sizeof(listnode))) == NULL) {
		printf("malloc failed\n");
		return -1;	
	}
	p->data = value;
	p->next = NULL;
	
	//2 locate locate locate   tail  node
	q = H;
	while(q->next != NULL){
		q = q->next;
	}

	//3 insert
	q->next =p;
	return 0;

}

int list_show(linklist H)
{
	linklist p;

	//S
	if(H == NULL) {
		printf("H is NULL\n");
		return -1;
	}

	p = H;
	while(p->next != NULL){
		printf("%d ", p->next->data);
		p = p->next;
	}
	puts("");

	return 0;
}


linklist list_get(linklist H, int pos){
	linklist p;
	int i;

	if(H == NULL){
		printf("H is NULL\n");
		return NULL;
	}

	if(pos == -1){
		return H;
	}

	if(pos < -1)
	{
		printf("pos is invalid\n");
		return NULL;
	}

	p = H;
	i = -1;
	while(i < pos){ //循环pos+1次
		p = p->next;
		if(p == NULL) { //p已经是空
			printf("pos is invalid\n");
			return NULL;
		}
		i++;
	}

	return p;
}

int list_insert(linklist H, data_t value, int pos){
	linklist p;
	linklist q;

	if(H == NULL){ //空列表或者位置无效
		printf("H is NULL\n");
		return -1;
	}
	
	//1 locate node p (pos-1)
	p = list_get(H,pos-1);
	if (p == NULL) {
		return -1;
	}

	//2 new node q 
	if((q = (linklist)malloc(sizeof(listnode))) == NULL) {
		printf(" malloc failed\n");
		return -1;
	}
	q->data = value;
	q->next = NULL; //孤立的新节点

	//3 insert
	q->next = p->next;
	p->next = q;

	return 0;
}

int list_delete(linklist H, int pos){
	linklist p;
	linklist q;

	//1
	if(H == NULL) {
		printf("H is NULL\n");
		return -1;
	}
	
	//2 locate prior
	p = list_get(H,pos-1);
	if(p == NULL)
		return -1;
	if(p->next == NULL){
		printf("delete is invalid\n");
		return -1;
	}

	//3 update list
	q = p->next;
	p->next = q->next; //p->next = p->next->next;

	//4 free
	printf("free:%d\n",q->data);
	free(q);
	q = NULL;

	return 0;
}


int list_reverse(linklist H){
	linklist p;
	linklist q;

	if(H == NULL) {
		printf("H is NULL\n");
		return -1;
	}

	if(H->next == NULL || H->next->next == NULL){
		return 0;
	}

	p = H->next->next;
	H->next->next = NULL;//将列表一分为二

	while(p != NULL){
		q = p;
		p = p->next;

		q->next = H->next;
		H->next = q;
	}
	return 0;
}

linklist list_adjmax(linklist H, data_t *value){
	linklist p,q,r;
	data_t sum;
	
	if(H == NULL){
		printf("H is NULL\n");
		return NULL;
	}

	if(H->next == NULL || H->next->next == NULL || H->next->next->next == NULL)
	{
		return H;
	}

	q = H->next;
	p = H->next->next; //p = q->next;
	r = q;
	sum = q->data + p->data;

	while(p->next != NULL){
		p = p->next;
		q = q->next;
		if(sum < q->data + p->data){
		   sum = q->data + p->data;
		   r = q;
		}
	}
	*value = sum;
	return r;
}


int list_merge(linklist H1, linklist H2){
	linklist p,q,r;

	if(H1 == NULL || H2 == NULL) {
		printf("H1 || H2 is NULL\n");
		return -1;
	}

	p = H1->next;
	q = H2->next;
	r = H1;
	H1->next = NULL;
	H2->next = NULL;

	while(p && q)
	{
		if(p->data <= q->data) {
			r->next = p;
			p = p->next;
			r = r->next;
			r->next = NULL;
		}else {
			r->next = q;
			q = q->next;
			r = r->next;
			r->next = NULL;
		}
	}
	if(p == NULL){
		r->next = q;
	}else{
		r->next = p;
	}
	return 0;
}


linklist list_free(linklist H){
	linklist p;

	if(H == NULL)
		return NULL;

	p = H;

	printf("free:");
	while(H != NULL) {
		p = H;
		printf("%d ", p->data);
		
		H = H->next;
		free(p);
	//H = H->next;
	}
	puts("");

	return NULL;
}

test.c


#include<stdio.h>
#include"linklist.h"

void  test_get();
void  test_insert();
void  test_free();
void  test_reverse();
void  test_adjmax();

int main(int argc, const char *argv[])
{
	linklist H1, H2;
	int a[] = {1,3,5,7,9};
	int b[] = {2,4,6,8,10};
	int i;

	H1 = list_create();
	if(H1 == NULL) 
		return -1;

	H2 = list_create();
	if(H2 == NULL)
		return -1;

	for(i = 0; i < sizeof(a)/sizeof(int);i++)
	{
		list_tail_insert(H1,a[i]);
	}

	for(i = 0; i < sizeof(b)/sizeof(int);i++)
	{
		list_tail_insert(H2,b[i]);
	}

	list_show(H1);
	list_show(H2);

	list_merge(H1,H2);
	printf("merge: \n");


	list_show(H1);
	list_show(H2);

	list_free(H1);
	list_free(H2);

	return 0;

}

void  test_get(){
		
	linklist H;
	int value;
	linklist p;

	H = list_create();
	if(H == NULL)
		return; //链表没有创建成功

	printf("input:");

	while(1) { //循环接收用户输入
		scanf("%d", &value);
		if(value == -1)
			break;
		list_tail_insert(H, value);
		printf("input:");
	
	}

	list_show(H);
//	list_insert(H, 100, 4); 
//	list_show(H);

	p = list_get(H, 4); // 2 5 7 9 
	if(p != NULL)
		printf("value=%d\n", p->data);
//	return ;
}

void test_insert(){

	linklist H;
	int value;
//	linklist p;

	H = list_create();
	if(H == NULL)
		return ; //链表没有创建成功

	printf("input:");

	while(1) { //循环接收用户输入
		scanf("%d", &value);
		if(value == -1)
			break;
		list_tail_insert(H, value);
		printf("input:");
	
	}

	list_show(H);
	list_insert(H, 100, 0);
	list_show(H);
}

void test_reverse(){
	
	linklist H;
	int value;
//	linklist p;

	H = list_create();
	if(H == NULL)
		return ; //链表没有创建成功

	printf("input:");

	while(1) { //循环接收用户输入
		scanf("%d", &value);
		if(value == -1)
			break;
		list_tail_insert(H, value);
		printf("input:");
	
	}

	list_show(H);
	list_reverse(H);
//	list_delete(H,2);
//	list_insert(H, 100, 4); //2 5 7 9 
	list_show(H);
	list_free(H);

}

void test_adjmax(){
	
	linklist H;
	int value;
	linklist p;
	int sum;

	H = list_create();
	if(H == NULL)
		return ; //链表没有创建成功

	printf("input:");

	while(1) { //循环接收用户输入
		scanf("%d", &value);
		if(value == -1)
			break;
		list_tail_insert(H, value);
		printf("input:");
	
	}

	list_show(H);
    p =	list_adjmax(H,&sum);
	if(p != NULL && p != H){
		printf("data=%d sum=%d\n", p->data,sum);
	}
//	list_reverse(H);
//	list_delete(H,2);
//	list_insert(H, 100, 4); //2 5 7 9 
	list_show(H);
	list_free(H);
}

void test_free(){

	linklist H;
	int value;
//	linklist p;

	H = list_create();
	if(H == NULL)
		return ; //链表没有创建成功

	printf("input:");

	while(1) { //循环接收用户输入
		scanf("%d", &value);
		if(value == -1)
			break;
		list_tail_insert(H, value);
		printf("input:");
	
	}

	list_show(H);
	list_delete(H,2);
//	list_insert(H, 100, 4); //2 5 7 9 
	list_show(H);
	list_free(H);

//	p = list_get(H, 3); // 2 5 7 9 
//	if(p != NULL)
//		printf("value=%d\n", p->data);

//	return 0;
}

6. 栈实现及应用

6.1 栈-顺序栈的原理

在这里插入图片描述

6.2 栈-顺序栈的实现1

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
先申请栈空间,再申请成员空间
在这里插入图片描述

6.3 栈-顺序栈的实现2

栈的释放:不像之前的链表需要每个结点都释放,是集体的释放(free(指针))。

sqstack.h

typedef int data_t;

typedef struct {
	data_t *data;
	int maxlen;
	int top;
}sqstack;

sqstack * stack_create(int len);
int stack_push(sqstack *s, data_t value);
int stack_empty(sqstack *s);
int stack_full(sqstack *s);
data_t stack_pop(sqstack *s);
data_t stack_top(sqstack *s);
int stack_clear(sqstack *s);
int stack_free(sqstack *s);

sqstack.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"sqstack.h"


sqstack *stack_create(int len){
	sqstack *s;
	
	if((s =(sqstack *)malloc(sizeof(sqstack))) == NULL) {
		printf("malloc sqstack failed\n");
		return NULL;
	}

	//实际存数据的空间
	if((s->data = (data_t *)malloc(len * sizeof(data_t))) == NULL) {
		printf("malloc data failed\n");
		free(s);//s->data是空
		return NULL;
	}

	memset(s->data, 0, len*sizeof(data_t));
	s->maxlen = len;
	s->top = -1; //刚开始是个空栈(就是个数组),下标就是栈顶的位置

	return s;
}

int stack_push(sqstack *s, data_t value){
	if(s == NULL) {
		printf("s is NULL\n");
		return -1;
	}

	if(s->top == s->maxlen-1) {
		printf("stack is full\n");
		return -1;
	}

	s->top++;
	s->data[s->top] = value;

	return 0;
}

/*
 *@ret 1-empty
 * */
int stack_empty(sqstack *s){
	if (s == NULL) {
		printf("s is NULL\n");
		return -1;
	}
	return (s->top == -1 ? 1 : 0);
}

/*
 *@ret 1-full
 * */
int stack_full(sqstack *s){
	if(s == NULL) {
		printf("s is NULL\n");
		return -1;
	}

	return (s->top == s->maxlen-1 ? 1 : 0);

}

data_t stack_pop(sqstack *s){
	s->top--;
	return (s->data[s->top+1]);//未对空间进行释放和覆盖,可以直接使用
}

data_t stack_top(sqstack *s){ //查看栈顶
	return (s->data[s->top]);
}

int stack_clear(sqstack *s){ //把栈里元素都清掉,不是释放内存,只要调整top就行
	if(s == NULL) {
		printf("s is NULL\n");
		return -1;
	}
	s->top = -1;
	return 0;
}

int stack_free(sqstack *s){
	if(s == NULL) {
		printf("s is NULL\n");
		return -1;
	}

	if(s->data != NULL)
		free(s->data);
	free(s);
	printf("free success\n");
	return 0;
}

test.c

#include<stdio.h>
#include"sqstack.h"

int main(int argc, const char *argv[])
{
	sqstack *s;

	s = stack_create(100);
	if(s == NULL)
		return -1;
	
	stack_push(s,10);
	stack_push(s,15);
	stack_push(s,20);
	stack_push(s,30);
	
	while(!stack_empty(s)) {
		printf("pop: %d \n", stack_pop(s));
	}

	stack_free(s);
	return 0;
}

6.4 栈-链式栈原理及实现

链表加了限制,只允许头结点插入和删除。
在这里插入图片描述
链式入栈:封装结点,头部插入
在这里插入图片描述
链式出栈:

  1. 先找一个指针存储
  2. 修改结点
  3. 释放空间
    注意:需要返回值,释放空间之后值就没有了,先保存值,再释放
    在这里插入图片描述
    在这里插入图片描述
    linstack.h
typedef int data_t;

typedef struct node {
	data_t data;
	struct node *next;
}listnode, *linkstack;

linkstack stack_create();
int stack_push(linkstack s, data_t value);
data_t stack_pop(linkstack s);
int stack_empty(linkstack s);
data_t stack_top(linkstack s);
linkstack stack_free(linkstack s);

linkstack.c

#include<stdio.h>
#include<stdlib.h>
#include"linkstack.h"


linkstack stack_create()
{
	linkstack s;

	s = (linkstack)malloc(sizeof(listnode));
	if(s == NULL) {
		printf("malloc failed\n");
		return NULL;
	}
	s->data = 0;
	s->next = NULL;

	return s;
}

int stack_push(linkstack s, data_t value){
	linkstack p	;

	if(s == NULL) {
		printf("s is NULL\n");
		return -1;
	}

	p = (linkstack)malloc(sizeof(listnode));
	if(p == NULL) {
		printf("malloc failed\n");
		return -1;
	}
	
	p->data = value;
	//p->next = NULL;
	p->next = s->next;
	s->next = p;

	return 0;

}

data_t stack_pop(linkstack s)
{
	linkstack p;
	data_t t;

	p = s->next;
	s->next = p->next;

	t = p->data;

	free(p);
	p=NULL;

	return t;

}

int stack_empty(linkstack s){
	if(s == NULL) {
		printf("s is NULL\n");
		return -1;
	}
	return (s->next == NULL ? 1 : 0);
}

data_t stack_top(linkstack s){
	return (s->next->data);
}

linkstack stack_free(linkstack s){
	linkstack p;

	if(s == NULL) {
		printf("s is NULL\n");
		return NULL;
	}

	while(s != NULL) {
		p  = s;
		s = s->next;
		printf("free: %d\n", p->data);
		free(p);
	}

	return NULL;
}

test.c

#include<stdio.h>
#include<stdlib.h>
#include"linkstack.h"

int main(int argc, const char *argv[])
{
	linkstack s;

	s = stack_create();
	if(s == NULL)
		return -1;

	stack_push(s,10);
	stack_push(s,20);
	stack_push(s,30);
	stack_push(s,40);
#if 0
	while(!stack_empty(s)) {
		printf("pop:%d\n", stack_pop(s));
	}
#endif

    s = stack_free(s); //让s存储一下返回值,防止s为野指针

	return 0;

}

7. 队列实现及其应用

7.1 顺序队列的原理

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

7.2 顺序队列的实现

在这里插入图片描述
sequeue.h

#include<stdio.h>
#include<stdlib.h>
#define N 128
typedef int datatype;

typedef struct {
	datatype data[N];
	int front;
	int rear;
}sequeue;

sequeue *queue_create();
int enqueue(sequeue *sq, datatype x );
datatype dequeue(sequeue *sq);
int queue_empty(sequeue *sq);
int queue_full(sequeue *sq);
int queue_clear(sequeue *sq);
sequeue *queue_free(sequeue *sq);

sequeue.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"sequeue.h"

sequeue *queue_create(){
	sequeue *sq;

	if((sq = (sequeue *) malloc(sizeof(sequeue))) == NULL)
	{
		printf("malloc failed\n");
		return NULL;
	}
	
	//初始化
	memset(sq->data, 0, sizeof(sq->data));
	sq->front = sq->rear = 0;
	return sq;

}

//入队
int enqueue(sequeue *sq, datatype x ){
	if(sq == NULL) {
		printf("sq is NULL\n");
		return -1;
	}

	if((sq->rear + 1) % N == sq->front){
		printf("sequeue id full\n");
		return -1;
	}

	sq->data[sq->rear] = x;
	sq->rear = (sq->rear + 1) % N;//rear更新

	return 0;
}

//出队
datatype dequeue(sequeue *sq){
	datatype ret;
	
	ret = sq->data[sq->front]; //讲队头先存起来

	sq->front = (sq->front + 1) % N;

	return ret;

}

int queue_empty(sequeue *sq){
	if(sq == NULL) {
		printf("sq is NULL\n");
		return -1;
	}

	return (sq->front == sq->rear ? 1 : 0);
}

int queue_full(sequeue *sq){
	if(sq == NULL) {
		printf("sq is NULL\n");
		return -1;
	}

	if((sq->rear + 1) % N == sq->front) {
		return 1;
	}
	else {
		return 0;
	}
}

int queue_clear(sequeue *sq){
	if(sq == NULL) {
		printf("sq is NULL\n");
		return -1;
	}

	sq->front = sq->rear = 0;

	return 0;
}

sequeue *queue_free(sequeue *sq){
	if(sq == NULL) {
		printf("sq is NULL\n");
		return NULL;
	}

	free(sq);
	sq = NULL;

	return NULL;
}

test.c

#include<stdio.h>
#include"sequeue.h"

int main(int argc, const char *argv[])
{
	sequeue *sq;
	
	if((sq = queue_create()) == NULL){
		return -1;
	}

	enqueue(sq, 10);
	enqueue(sq, 20);
	enqueue(sq, 30);

	while(!queue_empty(sq)){
		printf("dequeue:%d\n", dequeue(sq));
	}

	queue_clear(sq);
	return 0;
}

7.3 链式队列的原理

在这里插入图片描述
在这里插入图片描述

7.4 链式队列的实现

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
入队是队尾入,出队是队头出
封装结点:申请内存,p指向这段空间,更新队尾

出队:
把头结点删掉,front的next是谁,谁就是队头,5这个结点相当于头结点,里面的5就没有意义,相当于队头元素,相当于5出队。
在这里插入图片描述
删除结点:找一个指针指向待删除的结点,修改指针指向,在free

队列清空:类似Free,保留一个头结点
linkqueue.h

typedef int datatype;

typedef struct node{
	datatype data;
	struct node *next;
}listnode, *linklist;

typedef struct {
	linklist front;
	linklist rear;
}linkqueue;

linkqueue * queue_create();
int enqueue(linkqueue *lq, datatype x);
datatype dequeue(linkqueue *lq);
int queue_empty(linkqueue *lq);
int queue_clear(linkqueue *lq);
linkqueue * queue_free(linkqueue *lq);

linkqueue.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"linkqueue.h"


linkqueue * queue_create(){
	linkqueue *lq;

	if((lq = (linkqueue*)malloc(sizeof(linkqueue))) == NULL)
	{
		printf("malloc linkqueue failed\n");
		return NULL;
	}
	
	lq->front = lq->rear =(linklist)malloc(sizeof(listnode));
	if(lq->front == NULL) {
		printf("malloc node failed\n");
		return NULL;
	}

	lq->front->data = 0;
	lq->front->next = NULL;

	return lq;
}

int enqueue(linkqueue *lq, datatype x){
	linklist p;
	
	if(lq == NULL) {
		printf("lq is NULL\n");
		return -1;
	}

	if((p = (linklist)malloc(sizeof(listnode))) == NULL){
		printf("malloc node failed\n");
		return -1;
	}
	//孤立节点
	p->data = x;
	p->next = NULL;
	
	lq->rear->next = p;//跟原来的尾节点相连
	lq->rear = p; //更新队尾

	return 0;
}

datatype dequeue(linkqueue *lq){
 	linklist p;

	if(lq == NULL)
	{
		printf("lq is NULL\n");
		return -1;
	}

	p = lq->front;
	lq->front = p->next;
	free(p);
	p = NULL;

	return (lq->front->data);//返回出队的元素
}

int queue_empty(linkqueue *lq){
	if(lq == NULL) {
		printf("lq is NULL\n");
		return -1;
	}
	return (lq->front == lq->rear ? 1 : 0);
}

int queue_clear(linkqueue *lq){
	linklist p;
	
	if(lq == NULL) {
		printf("lq is NULL\n");
		return -1;
	}

	while(lq->front->next) {
		p = lq->front;
		lq->front = p->next;
		printf("clear_free: %d\n", p->data);
		free(p);
		p = NULL;
	}
	return 0;

}

linkqueue *queue_free(linkqueue *lq){
	linklist p;
	if(lq == NULL) {
		printf("lq is NULL\n");
		return NULL;
	}
	
	while(lq->front) {  //有没有头结点,非空
		p = lq->front;
		lq->front = p->next;
		printf("free:%d\n", p->data);
		free(p);
	}
	free(lq);

	//防止用户释放了列表还去使用,将调用者指针更新
	lq = NULL;

	return NULL;
}

test.c

#include<stdio.h>
#include"linkqueue.h"

int main(int argc, const char *argv[])
{
	linkqueue *lq;

	lq = queue_create();
	if(lq == NULL)
		return -1;

	enqueue(lq, 10);
	enqueue(lq, 20);
	enqueue(lq, 30);
	enqueue(lq, 40);
	/*
	while(!queue_empty(lq)){
		printf("dequeue:%d\n", dequeue(lq));
	}
*/
	queue_clear(lq);
	
	lq = queue_free(lq);
	return 0;
}

7.5 栈和队列的应用-球钟问题的原理

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.6 栈和队列的应用-球钟问题的实现

一个队列三个栈
在这里插入图片描述
检查队列是否升序?
在这里插入图片描述
linkqueue.h

typedef int datatype;

typedef struct node{
	datatype data;
	struct node *next;
}listnode, *linklist;

typedef struct {
	linklist front;
	linklist rear;
}linkqueue;

linkqueue * queue_create();
int enqueue(linkqueue *lq, datatype x);
datatype dequeue(linkqueue *lq);
int queue_empty(linkqueue *lq);
int queue_clear(linkqueue *lq);
linkqueue * queue_free(linkqueue *lq);

linkqueue.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"linkqueue.h"


linkqueue * queue_create(){
	linkqueue *lq;

	if((lq = (linkqueue*)malloc(sizeof(linkqueue))) == NULL)
	{
		printf("malloc linkqueue failed\n");
		return NULL;
	}
	
	lq->front = lq->rear =(linklist)malloc(sizeof(listnode));
	if(lq->front == NULL) {
		printf("malloc node failed\n");
		return NULL;
	}

	lq->front->data = 0;
	lq->front->next = NULL;

	return lq;
}

int enqueue(linkqueue *lq, datatype x){
	linklist p;
	
	if(lq == NULL) {
		printf("lq is NULL\n");
		return -1;
	}

	if((p = (linklist)malloc(sizeof(listnode))) == NULL){
		printf("malloc node failed\n");
		return -1;
	}
	//孤立节点
	p->data = x;
	p->next = NULL;
	
	lq->rear->next = p;//跟原来的尾节点相连
	lq->rear = p; //更新队尾

	return 0;
}

datatype dequeue(linkqueue *lq){
 	linklist p;

	if(lq == NULL)
	{
		printf("lq is NULL\n");
		return -1;
	}

	p = lq->front;
	lq->front = p->next;
	free(p);
	p = NULL;

	return (lq->front->data);//返回出队的元素
}

int queue_empty(linkqueue *lq){
	if(lq == NULL) {
		printf("lq is NULL\n");
		return -1;
	}
	return (lq->front == lq->rear ? 1 : 0);
}

int queue_clear(linkqueue *lq){
	linklist p;
	
	if(lq == NULL) {
		printf("lq is NULL\n");
		return -1;
	}

	while(lq->front->next) {
		p = lq->front;
		lq->front = p->next;
		printf("clear_free: %d\n", p->data);
		free(p);
		p = NULL;
	}
	return 0;

}

linkqueue *queue_free(linkqueue *lq){
	linklist p;
	if(lq == NULL) {
		printf("lq is NULL\n");
		return NULL;
	}
	
	while(lq->front) {  //有没有头结点,非空
		p = lq->front;
		lq->front = p->next;
		printf("free:%d\n", p->data);
		free(p);
	}
	free(lq);

	//防止用户释放了列表还去使用,将调用者指针更新
	lq = NULL;

	return NULL;
}


sqstack.h

typedef int data_t;

typedef struct {
	data_t *data;
	int maxlen;
	int top;
}sqstack;

sqstack * stack_create(int len);
int stack_push(sqstack *s, data_t value);
int stack_empty(sqstack *s);
int stack_full(sqstack *s);
data_t stack_pop(sqstack *s);
data_t stack_top(sqstack *s);
int stack_clear(sqstack *s);
int stack_free(sqstack *s);

sqstack.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"sqstack.h"


sqstack *stack_create(int len){
	sqstack *s;
	
	if((s =(sqstack *)malloc(sizeof(sqstack))) == NULL) {
		printf("malloc sqstack failed\n");
		return NULL;
	}

	//实际存数据的空间
	if((s->data = (data_t *)malloc(len * sizeof(data_t))) == NULL) {
		printf("malloc data failed\n");
		free(s);//s->data是空
		return NULL;
	}

	memset(s->data, 0, len*sizeof(data_t));
	s->maxlen = len;
	s->top = -1; //刚开始是个空栈(就是个数组),下标就是栈顶的位置

	return s;
}

int stack_push(sqstack *s, data_t value){
	if(s == NULL) {
		printf("s is NULL\n");
		return -1;
	}

	if(s->top == s->maxlen-1) {
		printf("stack is full\n");
		return -1;
	}

	s->top++;
	s->data[s->top] = value;

	return 0;
}

/*
 *@ret 1-empty
 * */
int stack_empty(sqstack *s){
	if (s == NULL) {
		printf("s is NULL\n");
		return -1;
	}
	return (s->top == -1 ? 1 : 0);
}

/*
 *@ret 1-full
 * */
int stack_full(sqstack *s){
	if(s == NULL) {
		printf("s is NULL\n");
		return -1;
	}

	return (s->top == s->maxlen-1 ? 1 : 0);

}

data_t stack_pop(sqstack *s){
	s->top--;
	return (s->data[s->top+1]);//未对空间进行释放和覆盖,可以直接使用
}

data_t stack_top(sqstack *s){ //查看栈顶
	return (s->data[s->top]);
}

int stack_clear(sqstack *s){ //把栈里元素都清掉,不是释放内存,只要调整top就行
	if(s == NULL) {
		printf("s is NULL\n");
		return -1;
	}
	s->top = -1;
	return 0;
}

int stack_free(sqstack *s){
	if(s == NULL) {
		printf("s is NULL\n");
		return -1;
	}

	if(s->data != NULL)
		free(s->data);
	free(s);
	printf("free success\n");
	return 0;
}

test.c

#include<stdio.h>
#include"linkqueue.h"
#include"sqstack.h"



int check(linkqueue *lq);

int main(int argc, const char*argv[])
{
	linkqueue *lq;
	


	sqstack *s_hour, *s_five, *s_min;
	int value;
	int i;
	int min = 0;

	if((lq = queue_create()) == NULL) {
		return -1;
	}

	for (i=1; i <=27; i++) {
		enqueue(lq,i);
	}

//创建三个栈
	if((s_hour = stack_create(11)) == NULL){
		return -1;
	}

	if((s_five = stack_create(11)) == NULL){
		return -1;
	}

	if((s_min = stack_create(4)) == NULL){
		return -1;
	}

	
	while(1) {
		min++;
		if(!queue_empty(lq)){
			value = dequeue(lq);
			if(!stack_full(s_min)){ //分钟栈不满5
				stack_push(s_min, value);
			} else{//分钟栈满5进位
				while(!stack_empty(s_min)) {
					enqueue(lq, stack_pop(s_min)); //将分钟栈清空入队
				}
				if(!stack_full(s_five)) { //不是00:59这种情况
					stack_push(s_five, value);  //对五分钟栈入栈
				}else {//是XX:59这种情况
					while(!stack_empty(s_five)){
						enqueue(lq, stack_pop(s_five));//对五分钟栈进行出栈入队
					}
					if(!stack_full(s_hour)) {//如果不是11:59这种情况
						stack_push(s_hour,value);//对小时栈进行入栈
					}else{
						while(!stack_empty(s_hour)) {//如果是11:59这种情况
							enqueue(lq, stack_pop(s_hour));
						}
						enqueue(lq, value);//将球放队列里面
						//0:0   要求队列顺序和开始一致
					
						if(check(lq) == 1) {
							break;   //检查队列是否是升序
						}
					}
				}
			}
		}
	}

	printf("total:%d\n",min);
	printf("dequeue:");

	while(!queue_empty(lq))
		printf("%d ", dequeue(lq));
		puts("");
	return 0;
}  
int check(linkqueue *lq) {
	linklist p;

	if(lq == NULL) {
		printf("lq is NULL\n");
		return -1;
	}

	p = lq -> front ->next;

	while(p && p->next) {
		if(p->data < p->next->data) {
			p = p->next;
		}else {
			return 0;
		}
	}
	return 1;
}

8. 树及实现

8.1 树的概念

8.2 二叉树的原理

在这里插入图片描述
在这里插入图片描述

8.3 二叉树的运算

在这里插入图片描述
在这里插入图片描述

8.4 二叉树的三种遍历

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

8.5 二叉树的层次遍历

在这里插入图片描述
注意:.h 文件只能包含一次.
解决办法:加上一个宏定义,第一次包含的时候,没定义就定义,宏成立。第二次包含的时候,宏有了,就不在包含。

在这里插入图片描述
tree.h

#ifndef _TREE_H_
#define _TREE_H_

typedef char data_t;

typedef struct node_t{
	data_t data;
	struct node_t *left;
	struct node_t *right;
}bitree;


bitree *tree_create();
void preorder(bitree *r);
void inorder(bitree *r);
void postorder(bitree *r);
void layerorder(bitree *r);
//层次遍历(按顺序遍历)

#endif

tree.c

#include<stdio.h>
#include<stdlib.h>
//#include"tree.h"
#include"linkqueue.h"


bitree *tree_create(){
	data_t ch;
	bitree *r;

	scanf("%c", &ch);
	if(ch == '#')
		return NULL;

	if((r = (bitree*)malloc(sizeof(bitree))) == NULL){
		printf("malloc failed\n");
		return NULL;
	}
	r->data  = ch;
	r->left  = tree_create();
	r->right = tree_create();
	return r;
}

void preorder(bitree *r){
	if(r == NULL) {
		return;
//	printf("%c", r->data);
	printf("%c", r->data);
	preorder(r->left);
	preorder(r->right);
	}
}

void inorder(bitree *r){
	
	if(r == NULL) {
		return;
	}
	
	inorder(r->left);
	printf("%c", r->data);
	inorder(r->right);
}

void postorder(bitree *r){

	if(r == NULL) {
		return;
	}
	postorder(r->left);
	postorder(r->right);
	printf("%c", r->data);
}

void layerorder(bitree *r) {
	linkqueue *lq;

	if((lq = queue_create()) == NULL)
		return;
	if(r == NULL)
		return;

	printf("%c", r->data);
	enqueue(lq,r);

	while(!queue_empty(lq)) {
		r = dequeue(lq);
		if(r->left) {
			printf("%c", r->left->data);
			enqueue(lq, r->left);
		}
		if(r->right) {
			printf("%c",r->right->data);
			enqueue(lq, r->right);
		}
	}
	puts("");
}

test.c

#include<stdio.h>
#include"tree.h"

int main(int argc, const char *argv[])
{
	bitree *r;

	if((r = tree_create()) == NULL)
		return -1;

	
	preorder(r);
	puts("");

	inorder(r);
	puts("");

	postorder(r);
	puts("");

    
	return 0;
}

9. 查找

9.1 查找的原理

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

9.2 hash原理

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
用得最多的方法:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

9.3 hash表的实现-创建

9.4 hash表的实现-插入和查找

封装结点 -> 放入hash表链表中
在这里插入图片描述
hash.h

#ifndef _HASH_
#define _HASH_

#define N 15

typedef int datatype;

typedef struct node{
	datatype key;
	datatype value;
	struct node *next;
}listnode, *linklist;

typedef struct{
	listnode data[N];
}hash;

hash *hash_create();
int hash_insert(hash *HT, datatype key);
linklist hash_search(hash *HT, datatype key);

#endif

hash.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"hash.h"

hash *hash_create() {
	hash *HT;
	if((HT = (hash*)malloc(sizeof(hash))) == NULL) {
		printf("malloc failed\n");
		return NULL;
	}

	memset(HT, 0, sizeof(hash));

	return HT;

}

int hash_insert(hash *HT, datatype key) {
	linklist p,q;

	if(HT == NULL) {
		printf("HT is NULL\n");
		return -1;
	}
	
	if((p = (linklist)malloc(sizeof(listnode))) == NULL){
		printf("malloc failed\n");
		return -1;
	}

	p->key = key;
	p->value = key % N;
	p->next = NULL;

	q = &(HT->data[key % N]);//锁定具体的列表,指向结点

	while(q->next && q->next->key < p->key) {//有序插入,找到带插入的前一个置
		q = q->next;
	}

	p->next = q->next;
	q->next = p;
	return 0;
}


linklist hash_search(hash *HT, datatype key) {
	linklist p;

	if(HT == NULL) {
		printf("HT is NULL\n");
		return NULL;
	}

	p = &(HT->data[key % N]);

	while(p->next && p->next->key != key) {
		p = p->next;
	}
	
	if(p->next == NULL) {//链表是空的
		return NULL;
	}else {
		printf("found\n");
		return p->next; //返回key所在结点的地址
	}
}


test.c

#include<stdio.h>
#include<stdlib.h>
#include"hash.h"

int main(int argc, const char*argv[])
{
	hash *HT;
	int data[] = {23, 34, 14, 38, 46, 16, 68, 15, 7, 31, 26};
	int i;
	int key;
	linklist r;
	

	if((HT = hash_create()) == NULL) {
		return -1;
	}

	for (i = 0; i < sizeof(data)/sizeof(int); i++) {
		hash_insert(HT, data[i]);
	}

	printf("input:");
	scanf("%d", &key);
	r = hash_search(HT, key);//返回
	if(r == NULL)
		printf("not found\n");
	else
		printf("found:%d %d\n", key, r->key);

	return 0;
}

10.排序

10.1 排序的原理

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

10.2 快速排序的实现

在这里插入图片描述

#include<stdio.h>
#include<stdlib.h>

#define N 15

int  partion(int *data, int low, int high);  //一趟递归处理
int  quick_sort(int *data, int low, int high);

int main(int argc, const char *argv[])
{
	int data[N] = {0};
	int i;

	srandom(10);

	for(i = 0; i < N; i++) {
		data[i] = random() % 100;
	}

	for(i = 0; i < N; i++) {
		printf("%d ", data[i]);
	}
    puts("");
	
	quick_sort(data, 0, N-1);
	for(i = 0; i < N; i++) {
		printf("%d ", data[i]);
	}
	puts("");
	return 0;
}

int quick_sort(int *data, int low, int high) {
	int t;

	if(data == NULL) {
		return -1;
	}

	if(low >= high)
		return 0;

	t = partion(data, low, high);//找到中轴
	quick_sort(data, low, t-1);
	quick_sort(data, t+1, high);

	return 0;
}

int partion(int *data, int low, int high) {
	int temp = data[low];

	while(low < high) {
		while(low < high && temp <= data[high]){ //需要考虑比所有数据都小的情况
			high--;
		}
		data[low] = data[high];

		while(low < high && temp >= data[low]){
			low++;
		}
		data[high] = data[low];
	}
	data[low] = temp;
	return low;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值