顺序表的顺序存储(增删查)
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 50
typedef int ElemType;//保证顺序表可以存储任何类型
//静态分配
typedef struct{
ElemType data[MaxSize];//定义的数组,用来存元素
int length;//当前顺序表中有多少个元素
}SqList;
//动态分配
#define InitSize 100
typedef struct{
ElemType *data;
int capacity;//动态数组的最大容量
int length;
}SeqList;
//i代表插入的位置,从1开始,e要插入的元素
bool ListInsert(SqList &L,int i,ElemType e)
{
if(i<1||i>L.length+1)//判断要插入的位置是否合法
return false;
if(L.length>=MaxSize)//超出空间了
return false;
for(int j=L.length;j>=i;j--)//移动顺序表中的元素,从最后一位开始元素依次往后移
L.data[j]=L.data[j-1];
L.data[i-1]=e;//数组下标从零开始,插入第一个位置,访问的下标为0
L.length++;
return true;//走到这里代表插入成功,返回true
}
//删除使用元素e的引用的目的是拿出对应的值
bool ListDelete(SqList &L,int i,ElemType &e)
{
if(i<1||i>L.length)//如果删除的位置是不合法
return false;
e=L.data[i-1];//获取顺序表中对应的元素,赋值给e
for(int j=i;j<L.length;j++)//从i的位置依次把元素往前覆盖
L.data[j-1]=L.data[j];//元素从后往前移
L.length--;//删除一个元素,顺序表长度减1
return true;
}
//查找成功,返回位置,位置从1开始,查找失败,返回0
int LocateElem(SqList L,ElemType e)
{
int i;
for(i=0;i<L.length;i++)//遍历顺序表
if(L.data[i]==e)
return i+1;//加1就是元素在顺序表中的位置
return 0;
}
//打印顺序表元素
void PrintList(SqList &L)
{
for(int i=0;i<L.length;i++)
{
printf("%4d",L.data[i]);//遍历数组,要求打印到一排
}
printf("\n");
}
int main()
{
SqList L;//顺序表的名称
bool ret;//查看返回值,布尔型是True,或者False
ElemType del;//要删除的元素
//首先手动在顺序表中赋值
L.data[0]=1;
L.data[1]=2;
L.data[2]=3;
L.length=3;//总计三个元素
//插入
ret=ListInsert(L,2,60);//将顺序表传入,往第二个位置插入60这个元素
if(ret)
{
printf("插入成功\n");
PrintList(L);//调用打印函数,打印成功后的顺序表
}else{
printf("插入失败\n");
}
//删除
ret=ListDelete(L,1,del);//把第一个位置的元素删除后存到del
if(ret)
{
printf("删除成功\n");
printf("删除元素值为 %d\n",del);
PrintList(L); //调用打印函数,打印删除成功后的顺序表
}else{
printf("删除失败\n");
}
//查找
ret=LocateElem(L,60);
if(ret)
{
printf("查找成功\n");
printf("元素位置为 %d\n",ret);
}else{
printf("查找失败\n");
}
system("pause");//停在控制台窗口
}
作业
初始化顺序表(表中元素为整形),里面元素为1,2,3通过scanf读取一个元素,插入到第二个位置,打印输出顺序表,每个元素占三个空格;然后通过scanf读取一个整型数是删除的位置。
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 100
typedef int ElemType;
typedef struct {
ElemType data[MaxSize];
int length;
}SqList;
bool ListInsert(SqList& L, int i, ElemType e)
//不需要在子函数中改变值的时候不需要加引用&,只是将它传进去
//要不要加引用,就是看是不是在子函数中去改变主函数中对应的变量,要改就加
{
if (i<1 || i>L.length + 1)
return false;
if (L.length >= MaxSize)
return false;
for (int j = L.length; j >= i; j--)
L.data[j] = L.data[j - 1];
L.data[i - 1] = e;
L.length++;
return true;
}
bool ListDelete(SqList& L, int i, ElemType& e)
//需要在子函数中改变值的时候才要加引用&
{
if (i<1 || i>L.length)
return false;
e = L.data[i - 1];
for (int j = i; j < L.length; j++)
L.data[j - 1] = L.data[j];
L.length--;
return true;
}
void PrintList(SqList& L)
{
for (int i = 0; i < L.length; i++)
{
printf("%3d", L.data[i]);
}
printf("\n");
}
int main()
{
SqList L;
bool ret_1;
bool ret_2;
ElemType del;
int add_p;
int del_p;
scanf("%d", &add_p);//读取添加的元素值
L.data[0] = 1;
L.data[1] = 2;
L.data[2] = 3;
L.length = 3;
ret_1 = ListInsert(L, 2, add_p);//读取的元素固定的放在第二个位置
if (ret_1)
{
PrintList(L);
}
else {
printf("false\n");
}
scanf("%d", &del_p);//读取删除元素的位置
ret_2 = ListDelete(L, del_p, del);
if (ret_2)
{
PrintList(L);
}
else {
printf("false\n");
}
}
//结构体指针day-01作业
输入一个学生的学号、姓名、性别,通过scanf读取后,通过printf打印输出
Input&output
101 xiongda m
#include <stdio.h>
#include <stdlib.h>
//结构体指针
struct student {
int num;
char name[20];
char sex;
};//声明一个结构体类型
int main()
{
Struct student s;
Scanf(“%d %s %c”,&s.num,s.name,&s.sex); //数组名中存的是数组的起始地址,scanf中不用加&。
Printf(“%d %s %c\n”,s.num,s.name,s,sex); //Scanf传递时,为什么后面要加一个地址,指针的传递的使用场景
return 0;
}
//C++的引用作业
在主函数中定义字符指针char*p,在子函数中malloc申请空间,通过fgets读取字符串,然后在主函数中输出,要求子函数中使用c++的引用
#include <stdio.h>
#include <stdlib.h>
void modify_pointer(char*& p)//在子函数内操作p和主函数操作p手法一致
{
p = (char*)malloc(100);
fgets(p,100,stdin);//如果fgets传入的是一个指针变量,中间参数是指针指向的空间大小
}
int main()
{
Char* p;
Modify_pointer(p);
Puts(p);
return 0;
}
线性表的链式存储(重点)
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;
typedef struct LNode{
ElemType data;
struct LNode *next;//指向下一个结点
}LNode,*LinkList;//此处的LinkList等价于struct LNode*
//头插法新建链表(重点)
LinkList CreatList1(LinkList &L)//list_head_insert
{
LNode *s;int x;//s为新节点
L=(LinkList)malloc(sizeof(LNode));//带头结点的链表,不带头结点
L->next=NULL;//L->data里边没放东西
scanf("%d",&x);//从标准输入读取数据
//3 4 5 6 7 9999
while(x!=9999){
s=(LNode*)malloc(sizeof(LNode));//申请一个新空间给s,强制类型转换
s->data=x;//把读取到的值,给新空间中的data成员
s->next=L->next;//让新节点的next指针指向链表的第一个元素(第一个放我们数据的元素)
L->next=s;//指向s之后,原来的指针就断了,s作为第一个元素
scanf("%d",&x);//读取标准输入
}
return L;
}
//尾插法新建链表(重点)
LinkList CreatList2(LinkList &L)//list_tail_insert
{
int x;
L=(LinkList)malloc(sizeof(LNode));//带头节点的链表
LNode *s,*r=L;//r与s都是结构体指针,r代表链表表尾节点,指向链表尾部
//3 4 5 6 7 9999
scanf("%d",&x);
while(x!=9999){
s=(LNode*)malloc(sizeof(LNode));
s->data=x;
r->next=s;//让尾部节点指向新节点
r=s;//r指向新的表尾结点
scanf("%d",&x);
}
r->next=NULL;//尾结点的next指针赋值为NULL
return L;
}
//按序号查找结点值
LNode *GetElem(LinkList L,int i)
{
int j=1;
LNode *p=L->next;//移动后指向头节点后的第一个元素a1
if(i==0)
return L;//查找第零个位置,则认为查找的是头节点
if(i<1)
return NULL;//i是负值则返回空
while(p&&j<i)//保证p不是空指针且j<i
{
p=p->next;//让p指向下一个节点
j++;
}
return p;
}
//按值查找(遍历链表,判断是否与e相等)
LNode *LocateElem(LinkList L,ElemType e)
{
LNode *p=L->next;
while(p!=NULL&&p->data!=e)
p=p->next;
return p;
}
//新结点e插入到第i个位置
bool ListFrontInsert(LinkList L,int i,ElemType e)
{
LinkList p=GetElem(L,i-1);//返回为i-1,指针类型,拿到要插入位置前一个位置的地址值
if(NULL==p)
{
return false;//i不对,太大或为负值
}
LinkList s=(LNode*)malloc(sizeof(LNode));//为新插入的结点申请空间
s->data=e;//要插入的值放入对应的空间
s->next=p->next;//插入步骤
p->next=s;
return true;
}
//删除第i个结点
bool ListDelete(LinkList L,int i)
{
LinkList p=GetElem(L,i-1);//查找删除位置的前驱节点,使其指向要删除节点的后继节点,然后free要删除的节点
if(NULL==p)
{
return false;//要删除的位置不对
}
LinkList q;
q=p->next;//此时q指向要删除的节点
if(NULL == q){
return false;//要删除的位置不存在
}
p->next=q->next;//删除节点的前驱节点指向删除节点的后继节点,断链。
free(q);//释放对应结点的空间
return true;
}
//打印链表中每个结点的值
void PrintList(LinkList L)
{
L=L->next;
while(L!=NULL)//L等于NULL,已经访问完最后一个节点
{
printf("%3d",L->data);//打印当前节点数据
L=L->next;//指向下一个节点
}
printf("\n");
}
//《王道C督学营》课程
//2.3 线性表的链式表示
int main()
{
LinkList L;//链表头,是结构体指针类型
LinkList search;//用来存储拿到的某一个节点
CreatList1(L);//输入数据可以为3 4 5 6 7 9999(头插法)
CreatList2(L);//输入数据可以为3 4 5 6 7 9999(尾插法)
PrintList(L);//链表打印
search=GetElem(L,2);//查找链表L第二个位置元素的值
if(search!=NULL)
{
printf("按序号查找成功\n");
printf("%d\n",search->data);
}
search=LocateElem(L,6);//按值查询
if(search!=NULL)
{
printf("按值查找成功\n");
printf("%d\n",search->data);
}
ListFrontInsert(L,2,99);//新结点99插入第(2)i个位置
PrintList(L);
ListDelete(L,4);//删除第4个结点
PrintList(L);
system("pause");
}
头插法与尾插法原理
双向链表(次要)
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;
typedef struct DNode{
ElemType data;
struct DNode *prior,*next;//前驱,后继
}DNode,*DLinkList;
//双向链表头插法
DLinkList Dlist_head_insert(DLinkList &DL)
{
DNode *s;int x;
DL=(DLinkList)malloc(sizeof(DNode));//带头结点的链表,DL为头节点
DL->next=NULL;//前驱与后继都填上NULL
DL->prior=NULL;
scanf("%d",&x);//从标准输入读取数据
//3 4 5 6 7 9999
while(x!=9999){
s=(DLinkList)malloc(sizeof(DNode));//申请一个空间空间,强制类型转换
s->data=x;
s->next=DL->next;//要插入的节点向后指向头节点的下一个节点:1
if(DL->next!=NULL)//插入第一个结点时,不需要这一步操作
{
DL->next->prior=s;//头节点的下一个节点向前指向要插入的节点:2
}
s->prior=DL;//要插入的节点指向头节点:3
DL->next=s;//头节点指向要插入的节点:4
scanf("%d",&x);//读取标准输入
}
return DL;
}
//双向链表尾插法
DLinkList Dlist_tail_insert(DLinkList &DL)
{
int x;
DL=(DLinkList)malloc(sizeof(DNode));//带头节点的链表
DNode *s,*r=DL;//r代表尾指针
DL->prior=NULL;
//3 4 5 6 7 9999
scanf("%d",&x);
while(x!=9999){
s=(DNode*)malloc(sizeof(DNode));
s->data=x;
r->next=s;
s->prior=r;
r=s;//r指向新的表尾结点
scanf("%d",&x);
}
r->next=NULL;//尾结点的next指针赋值为NULL
return DL;
}
//按序号查找结点值
DNode *GetElem(DLinkList DL,int i)
{
int j=1;
DNode *p=DL->next;
if(i==0)
return DL;
if(i<1)
return NULL;
while(p&&j<i)
{
p=p->next;
j++;
}
return p;
}
//新结点插入第i个位置
bool DListFrontInsert(DLinkList DL,int i,ElemType e)
{
DLinkList p=GetElem(DL,i-1);//找前一个位置的地址
if(NULL==p)
{
return false;
}
DLinkList s=(DLinkList)malloc(sizeof(DNode));//为新插入的结点申请空间
s->data=e;
s->next=p->next;
p->next->prior=s;
s->prior=p;
p->next=s;
return true;
}
//删除第i个结点
bool DListDelete(DLinkList DL,int i)
{
DLinkList p=GetElem(DL,i-1);//删除首先要找到前一个节点
if(NULL==p)
{
return false;
}
DLinkList q;
q=p->next;
if(q==NULL)//删除的元素不存在
return false;
p->next=q->next;//1:a指向c,断链
if(q->next!=NULL)
{
q->next->prior=p;//2:c指向a。
}
free(q);//释放对应结点的空间
return true;
}
//链表打印
void PrintDList(DLinkList DL)
{
DL=DL->next;
while(DL!=NULL)
{
printf("%3d",DL->data);
DL=DL->next;
}
printf("\n");
}
//《龙哥带你撸代码》课程
//2.3.3 双链表增删查
int main()
{
DLinkList DL;
DLinkList search;
Dlist_head_insert(DL);
//Dlist_tail_insert(DL);
//3 4 5 6 7 9999
PrintDList(DL);
search=GetElem(DL,2);
if(search!=NULL)
{
printf("按序号查找成功\n");
printf("%d\n",search->data);
}
DListFrontInsert(DL,3,99);
PrintDList(DL);
DListDelete(DL,2);
PrintDList(DL);
system("pause");
}
Why需要在形参的地方使用引用?
在子函数中给对应的形参赋值后,子函数结束,主函数中对应的实参发生了变化。
如果没有使用引用,在子函数中给对应的形参赋值后,子函数结束,主函数中对应的实参不会发生变化。
栈和队列-中级-day06
栈的顺序存储(简单)
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 50
typedef int ElemType;
typedef struct{
ElemType data[MaxSize];//数组
int top;
}SqStack;
//初始化栈
void InitStack(SqStack &S)
{
S.top=-1;//代表栈为空,初始化时-1
}
//布尔类型:用来判断栈是否为空
bool StackEmpty(SqStack &S)
{
if(S.top==-1)
return true;
else
return false;
}
//入栈
bool Push(SqStack &S,ElemType x)//ElemType可以指代任何数据类型
{
If(S.top==MaxSize-1)//数组的大小不能改变,避免访问越界
//栈满:s.top=MaxSize-1,因为数组下标从零开始
{
return false;//栈满了,不能再入栈了
}
S.data[++S.top]=x;//s.top指向当前栈顶的数组下标,先自加s.top后移,x赋值给s.top
return true;//返回true,入栈成功
}
//出栈
bool Pop(SqStack &S,ElemType &x)
{
if(-1==S.top)//栈为空
return false;
x=S.data[S.top--];//后减减,先x=S.data[S.top];拿到栈顶元素;后S.top=S.top-1;
return true;
}
//读取栈顶元素,返回值为布尔类型
bool GetTop(SqStack &S,ElemType &x)
{
if(-1==S.top)//说明栈为空,s.top=0时,有一个元素
return false;
x=S.data[S.top];//读取栈顶元素
return true;
}
//《王道C督学营》课程
//王道数据结构 3.1 栈
//实现栈 可以用数组,也可以用链表,我们这里使用数组
int main()
{
SqStack S;//定义一个栈,先进后出 FILO LIFO
bool flag;//布尔类型:用来判断栈是否为空
ElemType m;//用来存放拿出的元素
InitStack(S);//初始化
flag=StackEmpty(S);
if(flag)
{
printf("栈是空的\n");
}
//入栈3,4,5
Push(S,3);//入栈元素3
Push(S,4);//入栈元素4
Push(S,5);
flag=GetTop(S,m);//获取栈顶元素,栈顶指针不变
if(flag)
{
printf("获取栈顶元素为 %d\n",m);
}
flag=Pop(S,m);//弹出栈顶元素
if(flag)
{
printf("弹出元素为 %d\n",m);
}
system("pause");
}
链表实现栈,用的是头部插入法,头部删除法(次要)
循环队列
循环队列原理
队尾入队,队头出队
每入一次对,rear+1
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 5
typedef int ElemType;
typedef struct{
ElemType data[MaxSize];//数组,存储MaxSize-1个元素,牺牲一个存储单元来区别对空与对满
int front,rear;//队列头 队列尾
}SqQueue;
//初始化队列
void InitQueue(SqQueue &Q)
{
Q.rear=Q.front=0;
}
//判空
bool isEmpty(SqQueue &Q)
{
if(Q.rear==Q.front)//不需要为零
return true;
else
return false;
}
//入队
bool EnQueue(SqQueue &Q,ElemType x)
{
if((Q.rear+1)%MaxSize==Q.front) //判断是否队满
return false;
Q.data[Q.rear]=x;//队尾放入元素,Q.rear指向队尾元素。每入一次对,rear+1
3 4 5 6
Q.rear=(Q.rear+1)%MaxSize;
return true;
}
//出队
bool DeQueue(SqQueue &Q,ElemType &x)
{
if(Q.rear==Q.front)//队列为空,不能出队
return false;
x=Q.data[Q.front];//先进先出
Q.front=(Q.front+1)%MaxSize;
return true;
}
//《王道C督学营》课程
//王道数据结构 3.2 循环队列
int main()
{
SqQueue Q;
bool ret;//存储返回值
ElemType element;//存储出队元素
InitQueue(Q);//初始化队列
ret=isEmpty(Q);
if(ret)
{
printf("队列为空\n");
}else{
printf("队列不为空\n");
}
EnQueue(Q,3);
EnQueue(Q,4);
EnQueue(Q,5);
ret=EnQueue(Q,6);
ret=EnQueue(Q,7);
if(ret)
{
printf("入队成功\n");
}else{
printf("入队失败\n");
}
ret=DeQueue(Q,element);
if(ret)
{
printf("出队成功,元素值为 %d\n",element);
}else{
printf("出队失败\n");
}
ret=DeQueue(Q,element);
if(ret)
{
printf("出队成功,元素值为 %d\n",element);
}else{
printf("出队失败\n");
}
ret=EnQueue(Q,8);
if(ret)
{
printf("入队成功\n");
}else{
printf("入队失败\n");
}
system("pause");
}
队列的链式存储
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;
typedef struct LinkNode{
ElemType data;
struct LinkNode *next;
}LinkNode;//链表节点结构体
typedef struct{
LinkNode *front,*rear;//链表头 链表尾
}LinkQueue;//先进先出(队列的结构体)
void InitQueue(LinkQueue &Q)
{
Q.front=Q.rear=(LinkNode*)malloc(sizeof(LinkNode));//头和尾指向申请的同一个空间结点
Q.front->next=NULL;//头节点的Next指针为NULL
}
bool IsEmpty(LinkQueue Q)
{
if(Q.front==Q.rear)
return true;
else
return false;
}
//入队,尾部插入法
void EnQueue(LinkQueue &Q,ElemType x)
{
LinkNode *s=(LinkNode *)malloc(sizeof(LinkNode));//给x申请空间
s->data=x;s->next=NULL;//将x赋给s;
Q.rear->next=s;//rear始终指向尾部
Q.rear=s;
}
//出队 头部删除法
bool DeQueue(LinkQueue &Q,ElemType &x)
{
if(Q.front==Q.rear) return false;//队列为空
LinkNode *p=Q.front->next;//头结点什么都没存,所以头结点的下一个节点才有数据
x=p->data;
Q.front->next=p->next;//使头指针指向要删除节点的后一个节点,断链
if(Q.rear==p)//删除的是最后一个元素
Q.rear=Q.front;//队列置为空
free(p);
return true;
}
//《王道C督学营》课程
//王道考研数据结构 3.2.3 队列的链式存储
//头部删除法,尾部插入法
int main()
{
LinkQueue Q;
bool ret;
ElemType element;//存储出队元素
InitQueue(Q);//初始化队列
//入队
EnQueue(Q,3);
EnQueue(Q,4);
EnQueue(Q,5);
EnQueue(Q,6);
EnQueue(Q,7);
ret=DeQueue(Q,element);
if(ret)
{
printf("出队成功,元素值为 %d\n",element);
}else{
printf("出队失败\n");
}
system("pause");
}
作业:
#include <stdio.h>
#include <stdlib.h>
//Fib是递归函数
int Fib(int n)
{
if(n==0)
return 0;
else if(n==1)
return 1;
else
return Fib(n-1)+Fib(n-2);
}
//王道数据结构 斐波那契数列(每一个数都等于前两个数之和)
//递归 函数调用自身
//0 1 1 2 3 5
//f(n)=f(n-1)+f(n-2)
//考研不是很重要,了解即可
int main()
{
int num;
while(scanf("%d",&num)!=EOF)
{
printf("Fib(%d) = %d\n",num,Fib(num));
}
system("pause");
}
//题目 n个台阶,每次只能上1个台阶,或者2个台阶,n个台阶,有多少种走法
中级-day04-作业
Q:
输入3 4 5 6 7 9999一串整数,9999代表结束,通过头插法新建链表并输出;通过尾插法新建链表并输出
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;
typedef struct LNode {
ElemType data;
struct LNode* next;//指向下一个结点
}LNode, * LinkList;
//头插法新建链表
LinkList CreatList1(LinkList& L)//list_head_insert
{
LNode* s; int x;
L = (LinkList)malloc(sizeof(LNode));//带头结点的链表
L->next = NULL;//L->data里边没放东西
scanf("%d", &x);//从标准输入读取数据
//3 4 5 6 7 9999
while (x != 9999) {
s = (LNode*)malloc(sizeof(LNode));//申请一个新空间给s,强制类型转换
s->data = x;//把读取到的值,给新空间中的data成员
s->next = L->next;//让新结点的next指针指向链表的第一个元素(第一个放我们数据的元素)
L->next = s;//让s作为第一个元素
scanf("%d", &x);//读取标准输入
}
return L;
}
//尾插法新建链表
LinkList CreatList2(LinkList& L)//list_tail_insert
{
int x;
L = (LinkList)malloc(sizeof(LNode));//带头节点的链表
LNode* s, * r = L;//LinkList s,r=L;也可以,r代表链表表尾结点,指向链表尾部
//3 4 5 6 7 9999
scanf("%d", &x);
while (x != 9999) {
s = (LNode*)malloc(sizeof(LNode));
s->data = x;
r->next = s;//让尾部结点指向新结点
r = s;//r指向新的表尾结点
scanf("%d", &x);
}
r->next = NULL;//尾结点的next指针赋值为NULL
return L;
}
//打印链表中每个结点的值
void PrintList(LinkList L)
{
L = L->next;//让L指向第一个有数据的结点
while (L != NULL)
{
printf("%d", L->data);//打印当前结点数据
L = L->next;//指向下一个结点
if (L != NULL)
{
printf(" ");
}
}
printf("\n");
}
//《王道C督学营》课程
int main()
{
LinkList L = NULL;//链表头,是结构体指针类型
LinkList search;//用来存储拿到的某一个节点
CreatList1(L);//输入数据可以为3 4 5 6 7 9999,头插法新建链表
PrintList(L);//链表打印
CreatList2(L);//输入数据可以为3 4 5 6 7 9999
PrintList(L);
return 0;
}
中级-day05-作业
Q:输入3 4 5 6 7 9999一串整数,9999代表结束,通过尾插法新建链表,查找第二个位置的值并输出,在第二个位置插入99,输出为 3 99 4 5 6 7,删除第四个位置的值,打印输出为3 99 4 5 6 7
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;
typedef struct LNode {
ElemType data;
struct LNode* next;//指向下一个结点
}LNode, * LinkList;
//头插法新建链表
LNode* CreatList1(LinkList& L)//list_head_insert
{
LNode* s; int x;
L = (LinkList)malloc(sizeof(LNode));//带头结点的链表
L->next = NULL;//L->data里边没放东西
scanf("%d", &x);//从标准输入读取数据
//3 4 5 6 7 9999
while (x != 9999) {
s = (LNode*)malloc(sizeof(LNode));//申请一个新空间给s,强制类型转换
s->data = x;//把读取到的值,给新空间中的data成员
s->next = L->next;//让新结点的next指针指向链表的第一个元素(第一个放我们数据的元素)
L->next = s;//让s作为第一个元素
scanf("%d", &x);//读取标准输入
}
return L;
}
//尾插法新建链表
LinkList CreatList2(LinkList& L)//list_tail_insert
{
int x;
L = (LinkList)malloc(sizeof(LNode));//带头节点的链表
LNode* s, * r = L;//LinkList s,r=L;也可以,r代表链表表尾结点,指向链表尾部
//3 4 5 6 7 9999
scanf("%d", &x);
while (x != 9999) {
s = (LNode*)malloc(sizeof(LNode));
s->data = x;
r->next = s;//让尾部结点指向新结点
r = s;//r指向新的表尾结点
scanf("%d", &x);
}
r->next = NULL;//尾结点的next指针赋值为NULL
return L;
}
//打印链表
void PrintList(LinkList L)
{
L = L->next;
while (L != NULL)//NULL是为了代表一张空的藏宝图
{
printf("%3d", L->data);//打印当前结点数据
L = L->next;//指向下一个结点
}
printf("\n");
}
//查找第几个结点的值
LinkList GetElem(LinkList L, int i)
{
int j = 1;
LinkList p = L->next;//让p指向第一个结点
if (0 == i)
{
return L;//i是零就返回头结点
}
if (i < 1)
{
return NULL;//i是负值就返回空
}
while (p && j < i)
{
p = p->next;//让p指向下一个结点
j++;
}
return p;
}
//按值查找
LinkList LocateElem(LinkList L, ElemType e)
{
LinkList p = L->next;
while (p != NULL && p->data != e)
{
p = p->next;
}
return p;
}
//往第i个位置插入元素
bool ListFrontInsert(LinkList L, int i, ElemType e)
{
LinkList p = GetElem(L, i - 1);//拿到要插入位置的前一个位置的地址值
if (NULL == p)
{
return false;//i不对
}
LinkList s = (LinkList)malloc(sizeof(LNode));//给新结点申请空间
s->data = e;//要插入的值放入对应空间
s->next = p->next;//插入步骤
p->next = s;
return true;
}
//删除第i个位置的元素
bool ListDelete(LinkList L, int i)
{
LinkList p = GetElem(L, i - 1);//查找删除位置的前驱节点
if (NULL == p)
{
return false;//要删除的位置不存在
}
LinkList q = p->next;
if (NULL == q)
{
return false;//要删除的位置不存在
}
p->next = q->next;//断链
free(q);//释放对应结点的空间
q = NULL;//为了避免野指针
return true;
}
//《王道C督学营》课程
//2.3 线性表的链式表示
int main()
{
LinkList L;//链表头,是结构体指针类型
LinkList search;//用来存储拿到的某一个节点
CreatList2(L);//输入数据可以为3 4 5 6 7 9999,尾插法
search = GetElem(L, 2);//查找链表第二个位置的元素值
if (search != NULL)
{
printf("%d\n", search->data);
}
ListFrontInsert(L, 2, 99);//新结点插入第i个位置
PrintList(L);//链表打印
ListDelete(L, 4);//删除第4个结点
PrintList(L);//打印注意格式
return 0;
}
中级-day06-作业(栈与队)
Q:新建一个栈,读取标准输入3个整数3 4 5,依次出栈,打印5 4 3新建循环队列(Maxsize=5),读取标准输入3 4 5 6 7,入队7时,对满,打印false,然后依次出队,输出3 4 5 6
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 5
typedef int ElemType;
typedef struct {
ElemType data[MaxSize];//数组
int top;
}SqStack;
void InitStack(SqStack& S)
{
S.top = -1;//代表栈为空
}
//入栈
bool Push(SqStack& S, ElemType x)
{
if (S.top == MaxSize - 1)//数组的大小不能改变,避免访问越界
{
return false;
}
S.data[++S.top] = x;
return true;
}
//出栈
bool Pop(SqStack& S, ElemType& x)
{
if (-1 == S.top)
return false;
x = S.data[S.top--];//后减减,x=S.data[S.top];S.top=S.top-1;
return true;
}
typedef int ElemType;
typedef struct {
ElemType data[MaxSize];//数组,存储MaxSize-1个元素
int front, rear;//队列头 队列尾
}SqQueue;
void InitQueue(SqQueue& Q)
{
Q.rear = Q.front = 0;
}
//入队
bool EnQueue(SqQueue& Q, ElemType x)
{
if ((Q.rear + 1) % MaxSize == Q.front) //判断是否队满
return false;
Q.data[Q.rear] = x;//3 4 5 6
Q.rear = (Q.rear + 1) % MaxSize;
return true;
}
//出队
bool DeQueue(SqQueue& Q, ElemType& x)
{
if (Q.rear == Q.front)
return false;
x = Q.data[Q.front];//先进先出
Q.front = (Q.front + 1) % MaxSize;
return true;
}
int main()
{
SqStack S;//先进后出 FILO LIFO
bool flag;
ElemType m;//用来存放拿出的元素
InitStack(S);//初始化
int i, num;
for (i = 0; i < 3; i++)
{
scanf("%d", &num);
Push(S, num);
}
for (i = 0; i < 3; i++)
{
Pop(S, m);
printf("%2d", m);
}
printf("\n");
SqQueue Q;
InitQueue(Q);
for (i = 0; i < 5; i++)//入队5个元素,最后一个元素不会入队成功
{
scanf("%d", &num);
flag=EnQueue(Q, num);
if (false == flag)
{
printf("false\n");
}
}
ElemType element;
for (i = 0; i < 4; i++)//出队4个元素并打印每一个
{
DeQueue(Q, element);
printf("%2d", element);
}
printf("\n");
}
中级-day07-树
将任意一个节点看作根都要满足树的条件,递归。
二叉树的遍历(链式存储)
用辅助队列层次建树
左指针指向左孩子;右指针指向右孩子。
Function.h
#include <stdio.h>
#include <stdlib.h>
//作者 王道训练营 龙哥
typedef char BiElemType;
typedef struct BiTNode{
BiElemType c;//c就是书籍上的data
struct BiTNode *lchild;
struct BiTNode *rchild;
}BiTNode,*BiTree;
typedef struct tag{//每一个链表中放一个树的指针
BiTree p;//树的某一个结点的地址值
struct tag *pnext;
}tag_t,*ptag_t;//辅助队列
//栈的相关数据结构
#define MaxSize 50
typedef BiTree ElemType;
typedef struct{
ElemType data[MaxSize];
int top;
}SqStack;
void InitStack(SqStack &S);
bool StackEmpty(SqStack &S);
bool Push(SqStack &S,ElemType x);
bool Pop(SqStack &S,ElemType &x);
bool GetTop(SqStack &S,ElemType &x);
//队列的相关数据结构
typedef struct LinkNode{
ElemType data;
struct LinkNode *next;
}LinkNode;
typedef struct{
LinkNode *front,*rear;
}LinkQueue;
void InitQueue(LinkQueue &Q);
bool IsEmpty(LinkQueue Q);
void EnQueue(LinkQueue &Q,ElemType x);
bool DeQueue(LinkQueue &Q,ElemType &x);
Main.cpp
#include "function.h"
//递归实现
//abdhiejcfg
//前序遍历(就是深度优先遍历)
void preOrder(BiTree p)
{
if(p!=NULL)
{
putchar(p->c);//等价于visit函数;上来打印当前节点,根-左-右
preOrder(p->lchild);//递归打印,代码执行过程为每次一颗子树
preOrder(p->rchild);
}
}
//中序遍历 hdibjeafcg
void InOrder(BiTree p)
{
if(p!=NULL)
{
InOrder(p->lchild);//左
putchar(p->c);//根
InOrder(p->rchild);//右
}
}
//后续遍历//hidjebfgca
void PostOrder(BiTree p)
{
if(p!=NULL)
{
PostOrder(p->lchild);//左
PostOrder(p->rchild);//右
putchar(p->c);//根
}
}
//中序遍历非递归,非递归执行效率更高,考的概率很低
void InOrder2(BiTree T)
{
SqStack S;
InitStack(S);//初始化一个栈
BiTree p=T;//p=树根
while(p||!StackEmpty(S))//逻辑或||
//栈不为空时为true,!StackEmpty(S)为false,p非空即可执行,两者皆空时循环结束,打印完成。
{
if(p)
//节点非空
{//不断压栈,并取其左孩子
Push(S,p);//将p压栈
p=p->lchild;
}else{
//节点为空,弹出栈中元素(弹自己)并打印,获取打印元素的右节点
Pop(S,p);putchar(p->c);//依次出栈,并打印该元素的右孩子
p=p->rchild;
}
}
}
//层次(层序)遍历,广度优先遍历,必须用到辅助队列
void LevelOrder(BiTree T)
{
LinkQueue Q;//辅助队列
InitQueue(Q);//初始化队列
BiTree p;
EnQueue(Q,T);//树根入队
while(!IsEmpty(Q))//判断队列是否为空
{
DeQueue(Q,p);//p拿到该元素,出队当前节点并打印
putchar(p->c);//打印
if(p->lchild!=NULL)//左孩子不为空,左孩子入队
EnQueue(Q,p->lchild);
if(p->rchild!=NULL)//右孩子不为空,右孩子入队
EnQueue(Q,p->rchild);
}
}
//《王道C督学营》课程
//二叉树的建树(层次建树=完全二叉树),前序、中序、后序遍历、中序非递归遍历、层次遍历
int main()
{
BiTree pnew;//接临时申请的空间
int i,j,pos;
char c;
BiTree tree=NULL;//定义一个树根,空指针
ptag_t phead=NULL,ptail=NULL,listpnew=NULL,pcur=NULL;//初始化指针
//phead就是队列头,ptail就是队列尾。在Function.h中。
//辅助队列:存放树的地址值
//abcdefghij
//用辅助队列层次建树:(判断phead的左右指针)
//a来,判断a的左指针是否为NULL,b来;判断a的右指针,c来,由辅助队列知,a的左右指针皆有所指,a出队,phead后移;此时判断b的左指针,放d,判断b的右指针,放e………
//树中申请空间存放数值;队列中申请空间存放指针。
while(scanf("%c",&c)!=EOF)//读取输入元素
{
if(c=='\n')
{
break;
}
pnew=(BiTree)calloc(1,sizeof(BiTNode));//calloc申请空间并对空间进行初始化,赋值为0---(树的节点分配)
pnew->c=c;//数据放进去
listpnew=(ptag_t)calloc(1,sizeof(tag_t));//给用链表实现的队列结点申请空间
listpnew->p=pnew;//队列中存放a的地址
if(NULL==tree)//根节点
{
tree=pnew;//树的根
phead=listpnew;//队列头
ptail=listpnew;//队列尾
pcur=listpnew;
continue;
}else{//左右孩子节点
ptail->pnext=listpnew;//新结点放入链表,通过尾插法
ptail=listpnew;//ptail始终指向队列尾部,有新地址时指针后移
}//pcur始终指向要插入的结点的位置
if(NULL==pcur->p->lchild)//如何把新结点放入树
{
pcur->p->lchild=pnew;//把新结点放到要插入结点的左边
}else if(NULL==pcur->p->rchild)
{
pcur->p->rchild=pnew;//把新结点放到要插入结点的右边
pcur=pcur->pnext;//左右都放了结点后,pcur指向队列的下一个
}
}
printf("--------前序遍历----------\n");
preOrder(tree);
printf("\n--------中序遍历------------\n");
InOrder(tree);
printf("\n--------后序遍历------------\n");
PostOrder(tree);
printf("\n--------中序遍历非递归------\n");//重要性低
InOrder2(tree);
printf("\n--------层次遍历-----------\n");
LevelOrder(tree);
printf("\n");
system("pause");
}
Stack.cpp
#include "function.h"
void InitStack(SqStack &S)
{
S.top=-1;
}
bool StackEmpty(SqStack &S)
{
if(S.top==-1)
return true;
else
return false;
}
//入栈
bool Push(SqStack &S,ElemType x)
{
if(S.top==MaxSize-1)
{
return false;
}
S.data[++S.top]=x;
return true;
}
//出栈
bool Pop(SqStack &S,ElemType &x)
{
if(-1==S.top)
return false;
x=S.data[S.top--];
return true;
}
//读取栈顶元素
bool GetTop(SqStack &S,ElemType &x)
{
if(-1==S.top)
return false;
x=S.data[S.top];
return true;
}
Queue.cpp
#include "function.h"
//带头结点的队列
void InitQueue(LinkQueue &Q)
{
Q.front=Q.rear=(LinkNode*)malloc(sizeof(LinkNode));
Q.front->next=NULL;
}
bool IsEmpty(LinkQueue Q)
{
if(Q.front==Q.rear)
return true;
else
return false;
}
void EnQueue(LinkQueue &Q,ElemType x)
{
LinkNode *s=(LinkNode *)malloc(sizeof(LinkNode));
s->data=x;s->next=NULL;
Q.rear->next=s;
Q.rear=s;
}
bool DeQueue(LinkQueue &Q,ElemType &x)
{
if(Q.front==Q.rear) return false;
LinkNode *p=Q.front->next;//头结点什么都没存,所以头结点的下一个节点才有数据
x=p->data;
Q.front->next=p->next;
if(Q.rear==p)
Q.rear=Q.front;
free(p);
return true;
}
二叉排序树
Main.cpp
#include <stdio.h>
#include <stdlib.h>
typedef int KeyType;
typedef struct BSTNode{
KeyType key;
struct BSTNode *lchild,*rchild;
}BSTNode,*BiTree;
//54,20,66,40,28,79,58
//插入函数
int BST_Insert(BiTree &T,KeyType k)
{
if(NULL==T)
{ //为新节点申请空间,第一个节点作为树根
T=(BiTree)malloc(sizeof(BSTNode));
T->key=k;
T->lchild=T->rchild=NULL;
return 1;//代表插入成功
}
else if(k==T->key)//要插入的节点值与当前节点值相等
return 0;//发现相同元素,就不插入
else if(k<T->key) //要插入的节点值小于当前节点值,递归
return BST_Insert(T->lchild,k);//函数调用结束后,左孩子会和原来的父亲通过引用关联起来
else
return BST_Insert(T->rchild,k);
}
//创建二叉排序树
void Creat_BST(BiTree &T,KeyType str[],int n)
{
T=NULL;
int i=0;
while(i<n)//遍历,每一次将一个元素放入二叉排序树中
{
BST_Insert(T,str[i]);
i++;
}
}
//递归算法简单,但执行效率较低,递归实现留给大家编写
BSTNode *BST_Search(BiTree T,KeyType key,BiTree &p)//(非递归)
{
p=NULL;//存储需要查找节点的父亲
while(T!=NULL&&key!=T->key)
{
p=T;
if(key<T->key) T=T->lchild;//比当前节点小,就左边找
else T=T->rchild;//比当前节点大,右边去
}
return T;
}
//这个书上没有二叉排序树;删除节点函数
void DeleteNode(BiTree &root,KeyType x){
if(root == NULL){
return;//空树
}
if(root->key>x){//树根大于该元素
DeleteNode(root->lchild,x);
}else if(root->key<x){//树根小于该元素
DeleteNode(root->rchild,x);
}else{ //恰好查找到了删除节点
if(root->lchild == NULL){ //左子树为空
BiTree tempNode = root;//用临时节点存储的目的是一会要free
root = root->rchild;//直接将其右子树上移替代root
free(tempNode);
}else if(root->rchild == NULL){ //右子树为空
BiTree tempNode = root;//临时指针
root = root->lchild; ;//直接将其左子树上移替代root
free(tempNode);
}else{ //左右子树都不为空
//一般的删除策略是左子树的最大数据(左子树中不断往右查找) 或 右子树的最小数据 代替要删除的节点(这里采用查找左子树最大数据来代替)
BiTree tempNode = root->lchild;//当54时拿到lchild 20
if(tempNode->rchild!=NULL){//20的右孩子不为空
tempNode = tempNode->rchild;//拿到20的右孩子40
}
root->key = tempNode->key;//40的值覆盖54
DeleteNode(root->lchild,tempNode->key);//将原来的40删除
}
}
}
//删除节点54
//删除原来的节点40
//删除54后最终的树
//中序遍历
void InOrder(BiTree T)
{
if(T!=NULL)
{
InOrder(T->lchild);
printf("%3d",T->key);
InOrder(T->rchild);
}
}
//《王道C督学营》课程
//二叉排序树的创建,中序遍历,查找,删除
int main()
{
BiTree T;//树根
BiTree parent;//存储父亲结点的地址值
BiTree search;
KeyType str[]={54,20,66,40,28,79,58};//将要进入二叉排序树的元素值
Creat_BST(T,str,7);//创建二叉排序树
InOrder(T);
printf("\n");
search=BST_Search(T,40,parent);//找到树中值为40的元素
if(search)
{
printf("找到对应结点,值=%d\n",search->key);
}else{
printf("未找到对应结点\n");//没找到的时候,返回NULL
}
DeleteNode(T,66);//删除66这个节点
InOrder(T);
printf("\n");
system("pause");
}
顺序查找与折半查找(二分查找)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef int ElemType;
typedef struct{
ElemType *elem;//整型指针
int TableLen;//存储动态数组里边元素的个数
}SSTable;
//暴力遍历
int Search_Seq(SSTable ST,ElemType key)
{
ST.elem[0]=key;//让零号元素作为哨兵
int i;
for(i=ST.TableLen-1;ST.elem[i]!=key;--i);//11-1=10,
return i;
}
//初始化元素,进行了随机数的生成
void ST_Init(SSTable &ST,int len)
{
ST.TableLen=len+1;//多申请了一个位置,为了存哨兵
ST.elem=(ElemType *)malloc(sizeof(ElemType)*ST.TableLen);//(10+1)*4
int i;
srand(time(NULL));//随机数生成
for(i=0;i<ST.TableLen;i++)//为啥这里零号位置也随机了数据,为折半查找服务
{
ST.elem[i]=rand()%100;
}
}
void ST_print(SSTable ST)
{
for(int i=0;i<ST.TableLen;i++)
{
printf("%3d",ST.elem[i]);
}
printf("\n");
}
//时间复杂度 logn
//二分查找
int Binary_Search(SSTable L,ElemType key)
{
int low=0,high=L.TableLen-1,mid;
while(low<=high)
{
mid=(low+high)/2;
if(L.elem[mid]==key)
return mid;//找到了
else if(L.elem[mid]>key)//要找的值小于mid
high=mid-1;
else//要找的值大于mid
low=mid+1;
}
return -1;
}
//compare函数
int compare(const void *left,const void *right)//left与right是任意两个元素的地址值
{
return *(ElemType*)left-*(ElemType*)right;//left元素的值-right元素的值,从小到大排序
}
//《王道C督学营》课程
//顺序查找 与 折半查找
int main()
{
SSTable ST;
ElemType key;
int pos;//存储查询元素的位置
ST_Init(ST,10);//初始化10个元素
ST_print(ST);
//顺序查找
printf("请输入要搜索的key值:\n");
scanf("%d",&key);
pos=Search_Seq(ST,key);//暴力遍历
if(pos)
{
printf("查找成功 位置为 %d\n",pos);
}else{
printf("查找失败\n");
}
//二分查找:数组必须是有序的
qsort(ST.elem,ST.TableLen,sizeof(int),compare);//qsort实现的是快排,qsort接口
// ST.elem:数组名,要排序数组的起始地址
// ST.TableLen:数组中元素的个数
// sizeof(int):每个元素所占空间的大小
// compare
ST_print(ST);
printf("二分查找,请输入要搜索的key值:\n");
scanf("%d",&key);
//有序数组
pos=Binary_Search(ST,key);
if(pos!=-1)
{
printf("查找成功 位置为 %d\n",pos);
}else{
printf("查找失败\n");
}
system("pause");
}
C语言文件操作
1、文件打开
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main(int argc,char *argv[])//argv[]:传进的参数以字符串形式,指针数组,指向传进来的每一个参数
{
//printf("argc=%d\n", argc);//argc:传递了多少个参数
//int i;
//for (i = 0; i < argc; i++)//将每一个参数输出出来
//{
// printf("%s\n", argv[i]);
//}
FILE* fp = fopen("file.txt", "w");//文件打开,fopen返回的是一个文件指针
//FILE* fp = fopen("file.txt", "r");//文件读取
//”w”:没有这个文件他会创建,有的话,他会删除里面的内容
if (NULL == fp)
{
perror("fopen");
return 0;//打开失败,程序直接结束
}
char c;
//读文件:用fgetc(fp)将整个文件读取出来
//while ((c = fgetc(fp)) != EOF)//EOF为-1,为文件尾;赋值运算符的优先级低,要加个括号
//{
// printf("%c", c);//打印字符
//}
//写文件:
//int ret;
//ret = fputc('H', fp);
//if (EOF == ret)
//{
// perror("fopen");
//}
fclose(fp);//关闭文件
return 0;
}
2、fread函数与fwrite函数
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main(int argc, char* argv[])
{
FILE* fp = fopen("file.txt", "r+");//文件打开
if (NULL == fp)
{
perror("fopen");
return 0;
}
char buf[128] = { 0 };
int ret;
strcpy(buf, "howareyou");
ret=fwrite(buf, sizeof(char), strlen(buf), fp);
memset(buf, 0, sizeof(buf));//清空
fseek(fp, 0, SEEK_SET);
ret = fread(buf, sizeof(char), 10, fp);//因为没有去设置errno的错误码,不能使用perror
puts(buf);
return 0;
}
3、fread与fwrite读写整型类型
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main(int argc, char* argv[])
{
FILE* fp = fopen("file.txt", "r+");//文件打开
if (NULL == fp)
{
perror("fopen");
return 0;
}
int i = 10;
fwrite(&i, sizeof(int), 1, fp);
fseek(fp, -5, SEEK_CUR);
int j = 0;
fread(&j, sizeof(int), 1, fp);
printf("j=%d\n", j);
fclose(fp);
}
中级-day11-交换/选择/插入/归并排序
快速排序:分治思想,不断递归,操场上一堆人,随便取一个人为分割值,比他矮站左边;比他高站右边;左右两边不断递归
#include <stdio.h>
#include <stdlib.h>
#include <time.h>//随机数接口
#include <string.h>
typedef int ElemType;
typedef struct{
ElemType *elem;//存储元素的起始地址
int TableLen;//元素个数
}SSTable;
//初始化函数
void ST_Init(SSTable &ST,int len)
{
ST.TableLen=len;
ST.elem=(ElemType *)malloc(sizeof(ElemType)*ST.TableLen);
int i;
srand(time(NULL));//骰子:随机数生成,每一次执行代码就会得到随机的10个元素
for(i=0;i<ST.TableLen;i++)
{
ST.elem[i]=rand()%100;//摇骰子:生成的是0-99之间
}
}
void ST_print(SSTable ST)
{
for(int i=0;i<ST.TableLen;i++)
{
printf("%3d",ST.elem[i]);
}
printf("\n");
}
void swap(ElemType &a,ElemType &b)
{
ElemType tmp;
tmp=a;
a=b;
b=tmp;
}
// 64 94 95 79 69 84 18 22 12 78
// 12 64 94 95 79 69 84 18 22 78
//王道冒泡
void BubbleSort(ElemType A[],int n)
{
int i,j;
bool flag;
for(i=0;i<n-1;i++)//i最多访问到8
{
flag=false;
for(j=n-1;j>i;j--)//把最小值就放在最前面
{
if(A[j-1]>A[j])
{
swap(A[j-1],A[j]);
flag=true;
}
}
if(false==flag)
return;
}
}
//冒泡排序
void BubbleSort1(ElemType A[], int n)
{
int i, j,flag;
for (i=0;i<n-1;i++)//i是控制有多少个有序了
{
flag = 0;
for (j = n-1; j>i;j--)//内层控制比较,交换
{
if (A[j - 1] > A[j])
{
swap(A[j - 1], A[j]);
flag = 1;
}
}
if (0 == flag)
{
break;
}
}
}
注:i用来遍历数组的下标;从3遍历到78
K:始终指向比40小的元素将要存的位置
// 64 94 95 79 69 84 18 22 12 78
//比64小的放在左边,比64大的放在右边
//王道:快速排序
//int Partition(ElemType A[],int low,int high)
//{
// ElemType pivot=A[low];
// while(low<high)
// {
// while(low<high&&A[high]>=pivot)
// --high;
// A[low]=A[high];
// while(low<high&&A[low]<=pivot)
// ++low;
// A[high]=A[low];
// }
// A[low]=pivot;
// return low;
//}
//龙哥:快速排序:qsort封装好的快排接口
int Partition1(int* arr, int left, int right)
{
int k, i; //k记录要放入比分割值小的数据的位置
for (i = left, k = left; i < right; i++) //不能写成0,应该为left, 递归时会变化
{
if (arr[i] < arr[right])
{
swap(arr[k], arr[i]);
k++; //k记录要放入比分割值小的数据的位置
}
}
swap(arr[k], arr[right]);
return k;
}
int Partition(int* arr, int left, int right)
{
int k, i;
for (k = i = left;i<right;i++)
{
if (arr[i] < arr[right])
{
swap(arr[i], arr[k]);
k++;
}
}
swap(arr[k], arr[right]);
return k;
}
//递归实现快速排序
void QuickSort(ElemType A[],int low,int high)// QuickSort(ST.elem,0,9);
{
if(low<high)
{
int pivotpos=Partition(A,low,high);//分割点左边的元素都比分割点要小,右边的比分割点大
QuickSort(A,low,pivotpos-1);//分割点左侧递归
QuickSort(A,pivotpos+1,high);//分割点右侧递归
}
}
//《王道C督学营》课程
//冒泡排序与快速排序
int main()
{
SSTable ST;
ElemType A[10]={ 64, 94, 95, 79, 69, 84, 18, 22, 12 ,78};
ST_Init(ST,10);//初始化
//memcpy(ST.elem,A,sizeof(A));//内存copy接口,当你copy整型数组,或者浮点型时,要用memcpy;从A copy到ST.elem,大小为sizeof(A).
ST_print(ST);//打印排序前的数组
//BubbleSort1(ST.elem,10);//冒泡排序
QuickSort(ST.elem,0,9);
ST_print(ST);//打印排序后的数组
system("pause");
}
中级-插入排序
插入排序:无序依次插入到有序中;
1有序,后边无序
1、2有序(2插入1),后边无序
1、2、3有序(3插入到1、2),后边无序
。。。。。//插入排序:哨兵:存放将要插入有序组的元素(每次先放后比)
从后往前遍历有序序列,比哨兵大的往后覆盖,比哨兵小的不用动,最后空位放哨兵。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef int ElemType;
typedef struct{
ElemType *elem;//整型指针
int TableLen;
}SSTable;
void ST_Init(SSTable &ST,int len)
{
ST.TableLen=len+1;//实际申请11个元素的空间
ST.elem=(ElemType *)malloc(sizeof(ElemType)*ST.TableLen);
int i;
srand(time(NULL));
for(i=0;i<ST.TableLen;i++)
{
ST.elem[i]=rand()%100;//随机了11个数,但是第一个元素是没有用到的
}
}
void ST_print(SSTable ST)
{
for(int i=0;i<ST.TableLen;i++)
{
printf("%3d",ST.elem[i]);
}
printf("\n");
}
//插入排序,从小到大排序,升序
void InsertSort(ElemType A[],int n)
{
int i,j;
//24 66 94 2 15 74 28 51 22 18 2
for(i=2;i<=n;i++)//第零个元素是哨兵,第一个元素自然有序;从第二个元素开始拿,往前面插入
{
if(A[i]<A[i-1])
{
A[0]=A[i];//放到暂存位置,A[0]即是暂存,也是哨兵
for(j=i-1;A[0]<A[j];--j)//移动元素,从后往前;内层循环控制有序序列中的每一个元素和要插入的元素(哨兵)比较
A[j+1]=A[j];
A[j+1]=A[0];//把暂存元素插入到对应位置
}
}
}
//折半查找 插入排序
void MidInsertSort(ElemType A[],int n)
{
int i,j,low,high,mid;
for(i=2;i<=n;i++)
{
A[0]=A[i];
low=1;high=i-1;
while(low<=high)//先通过二分查找找到待插入位置
{
mid=(low+high)/2;
if(A[mid]>A[0])
high=mid-1;
else
low=mid+1;
}
for(j=i-1;j>=high+1;--j)
A[j+1]=A[j];
A[high+1]=A[0];
}
}
//希尔排序
//多轮插入排序,考的概率很低,因为编写起来复杂,同时效率并不如快排,堆排
void ShellSort(ElemType A[],int n)
{
int dk,i,j;
// 73 29 74 51 29 90 37 48 72 54 83
for(dk=n/2;dk>=1;dk=dk/2)//步长变化
{
for(i=dk+1;i<=n;++i)//以dk为步长进行插入排序
{
if(A[i]<A[i-dk])
{
A[0]=A[i];
for(j=i-dk;j>0&&A[0]<A[j];j=j-dk)
A[j+dk]=A[j];
A[j+dk]=A[0];
}
}
}
}
//《王道C督学营》
int main()
{
SSTable ST;
ST_Init(ST,10);//实际申请了11个元素空间
ST_print(ST);
InsertSort(ST.elem,10);
//MidInsertSort(ST.elem,10);
//ShellSort(ST.elem,10);
ST_print(ST);
system("pause");
}