文章目录
数据结构与算法
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 栈-链式栈原理及实现
链表加了限制,只允许头结点插入和删除。
链式入栈:封装结点,头部插入
链式出栈:
- 先找一个指针存储
- 修改结点
- 释放空间
注意:需要返回值,释放空间之后值就没有了,先保存值,再释放
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;
}