数据结构
第一章 概论
1.常用的数据结构类型:集合
、线性
、树形
、图状
。
2.数据结构:
- 逻辑结构:数据元素之间的关系。
- 存储结构:数据结构在计算机中的表示。存储结构分为:顺序存储结构和链式存储结构。
3.算法是对特定问题求解步骤的一种描述,算法具有如下特性:有穷性、确定性、可行性、输入、输出。
4.算法的度量:
- 时间复杂度
- 空间复杂度
第二章 线性表
●顺序表
#include<stdio.h>
#include<stdlib.h>
#define maxsize 1024
typedef int datatype;
//定义顺序表结构体类型
typedef struct
{
datatype elem[maxsize];
int length;
}sequenlist;
sequenlist *L;
//初始化表
void InitList(sequenlist *L)
{
L->length=0;
}
//清空表
void ClearList(sequenlist *L)
{
L->length=0;
}
//元素定位
int Loc(sequenlist *L,datatype item)
{
int i,j;
j=(*L).length;
if(j==0)return false;
for(i=0;i<j;i++)
{
if((*L).elem[i]==item)return i;
}
printf("元素未找到!");
return -1;
}
//元素插入
int Ins(sequenlist *L,int i,datatype item)
{
int j;
if(i<1||i>(*L).length)return false;
for(j=(*L).length;j>i;j--)(*L).elem[j]=(*L).elem[j-1];
(*L).elem[i]=item;
(*L).length++;
return true;
}
//删除元素
int Del(sequenlist *L,int i)
{
int j;
if(i<1||i>(*L).length)return false;
for(j=i;j<(*L).length;j++)(*L).elem[j]=(*L).elem[j+1];
(*L).length--;
return true;
}
//添加元素
void createlist(sequenlist *L)
{
int n,i,c_type;
printf("请输入元素个数:");
scanf("%d",&n);
printf("请输入元素:\n");
for(i=0;i<n;i++)
{
printf("elem[%d]=",i);
fflush(stdin);
scanf("%d",&(*L).elem[i]);
printf("\n");
}
(*L).length=n;
}
//打印函数
void printout(sequenlist *L)
{
int i;
printf("--------当前表已更新--------\n");
for(i=0;i<(*L).length;i++)
printf("elem[%d]=%d -\n",i,(*L).elem[i]);
printf("----------------------------");
printf("\n\n\n");
};
//主函数
int main()
{
int button,e,w;
L=(sequenlist *)malloc(sizeof(sequenlist));
printf("4*1024+4=%d (64位系统 int 4 字节)\n",sizeof(int)*1024+sizeof(int));
printf("the byte of sequenlist:%d\n",sizeof(sequenlist));
createlist(L);
printf("-------------------菜单-------------------\n");
printf("1.元素定位 2.元素插入 3.元素删除 4.表查询\n");
while(true){
printf("功能选择:");
scanf("%d",&button);
switch(button){
case 1:printf("请输入元素:");
scanf("%d",&e);
printf("元素下标为:%d\n",Loc(L,e));
printout(L);
break;
case 2:printf("请输入元素:");
scanf("%d",&e);
printf("请输入元素插入的位置:");
scanf("%d",&w);
Ins(L,w,e);
printout(L);
break;
case 3:printf("请输入元素下标:");
scanf("%d",&e);
Del(L,e);
printout(L);
break;
case 4:printout(L);}
}
}
链表
●单链表
#include<stdio.h>
#include<stdlib.h>
typedef char elemtype;
//结点的数据类型定义
typedef struct LNode
{
elemtype data;
struct LNode *next;
}LinkList;
LinkList *L,*head;
//清空链表内容
int ClearList(LinkList *L)
{
LinkList *temp;
while(L->next!=NULL)
{
temp=L->next;
L->next=L->next->next;
free(temp);
}
}
//求链表长度
int ListLength(LinkList *L)
{
int len=0;
LinkList *temp;
temp=L;
while(temp->next!=NULL)
{
len++;
temp=temp->next;
}
return len;
}
//元素定位
int Loc(LinkList *L,elemtype item)
{
int i=0;
LinkList *temp;
temp=L->next;
while(temp!=NULL&&temp->data!=item)
{
i++;
temp=temp->next;
}
if(temp==0)return 0;
else return i;
}
//插入元素
int Ins(LinkList *L,int i,elemtype item)
{
int j=1;
LinkList *node,*temp;
node=(LinkList *)malloc(sizeof(LinkList));
if(node==NULL)return -1;
node->data=item;
temp=L->next;
if(temp==NULL)
{
if(i==0)
{
L->next=node;
node->next=NULL;
return 1;
}
else return -1;
}
while(j<i&&temp!=NULL)
{
temp=temp->next;
j++;
}
if(temp==NULL)return -1;
node->next=temp->next;
temp->next=node;
return 1;
}
//删除元素
int Del(LinkList*L,int i)
{
LinkList *temp,*p;
int j=1;
temp=L;
if(temp==NULL)return false;
while(j<i-1&&temp!=NULL)
{
j++;
temp=temp->next;
}
if(temp==NULL&&temp->next==NULL)return false;
p=temp->next;
temp->next=temp->next->next;
free(p);
return true;
}
//主函数
int main()
{
int s;
int item,i;
LinkList *L;
L=(LinkList *)malloc(sizeof(LinkList));
while(1)
{
printf("\n-----------------线性表-单链表---------------------");
printf("\n1.插入(以0开始) 2.定位 3.删除 4.求链表长度 5.清空链表");
printf("\n请选择功能:");
scanf("%d",&s);
if(s==1){
printf("请输入插入的数据:");
scanf("%d",&item);
printf("\n请输入插入的位置:");
scanf("%d",&i);
Ins(L,i,item);
printf("插入成功!");
fflush(stdin);
}
else if(s==2){
printf("请输入定位的数据:");
scanf("%d",&item);
printf("元素位置:%d",Loc(L,item));
Loc(L,item);
}
else if(s==3){
printf("请输入要删除的数据:");
scanf("%d",&item);
Del(L,item);
printf("删除成功!");
}
else if(s==4){
printf("当前链表的长度为:%d",ListLength(L));
}
else if(s==5){
ClearList(L);
printf("链表已清空!");
}
else printf("error!");
}
}
●循环链表
●双链表
第三章 栈与队列
●链栈
●顺序栈
#include<stdio.h>
#include<malloc.h>
#define maxsize 100
typedef int datatype;
typedef struct
{
datatype stack[maxsize];
int top;
}SeqStack;
//构造一个空栈
SeqStack *InitStack()
{
SeqStack *s;
s=(SeqStack *)malloc(sizeof(SeqStack));
if(!s){
printf("空间不足!");
return NULL;
}
else{
s->top=0;
return s;
}
}
//取栈顶元素
datatype GetTop(SeqStack *s)
{
if(s->top==0){
printf("栈是空的!");
return true;
}
else{
return s->stack[s->top-1];//小心越界
}
}
//入栈
SeqStack *Push(SeqStack *s,datatype x)
{
if(s->top==maxsize){
printf("栈是满的!");
return NULL;
}
else{
s->stack[s->top++]=x;
}
}
//出栈
SeqStack *Pop(SeqStack *s)
{
if(s->top==0){
printf("栈是空的!");
return false;
}
else
{
s->stack[(s->top)--];
return (SeqStack *)s->stack[s->top];
}
}
//判别空栈
int StackEmpty(SeqStack *s)
{
if(s->top==0){
printf("栈是空的!");
return true;
}
else return false;
}
//打印栈元素
void PrintElem(SeqStack *s)
{
int t;
t=s->top;
if(s->top==0)printf("the stack is empty!");
else
while(t!=0)
{
printf("%d->",s->stack[--t]);
}
}
//主函数
int main(){
int n,choice,e;
int a[n],i;
SeqStack *p;
p=InitStack();
printf("----------------------栈-顺序栈----------------------\n");
printf("请输入入栈的元素个数:");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf(">>[%d]=",i+1);
scanf("%d",&a[i]);
}
for(i=0;i<n;i++)Push(p,a[i]);
printf("output the stack values:");
PrintElem(p);
printf("\n");
printf("the stacktop value is %d",GetTop(p));
while(1){
printf("\n--------------------------------------");
printf("\n1.入栈 2.出栈 3.判断栈是否空 4.取栈顶元素 \n");
printf("请输入>>:");
scanf("%d",&choice);
switch(choice){
case 1:printf("请输入入栈元素:");scanf("%d",&e);Push(p,e);PrintElem(p);break;
case 2:printf("元素:%d 已出栈!\n",Pop(p));PrintElem(p);break;
case 3:printf("栈空:%d",StackEmpty(p));break;
case 4:printf("栈顶元素:%d",GetTop(p));break;
}
}
}
●顺序队列
●链队列
第四章 串
第五章 多维数组与广义表
第六章 树和二叉树
二叉树的定义和基本操作
1.二叉树的定义
- n(n>=0)个结点的有限集T构成,由左右子树组成,且左右子树都为二叉树。n=0时为空树。
2.二叉树分类
- 满二叉树 :一棵深度为k且有2^k -1个结点的二叉树。
- 完全二叉树:叶子结点只能出现在层次最大的两层上出现,和满二叉树的结点一一对应,当右分支层次为p时,左分支层次为p或p+1。
3.二叉树的性质
- 在二叉树的第i层上至多有2^(i-1)个结点(i>=1)
- 深度为k的二叉树至多有2^k -1个结点(k>=1)
- n0=n2+1(n0为子叶结点数 n2为度为2的结点数)
- 具有n个结点的完全二叉树的深度为[log2 n]+1
- 对于有n个结点的完全二叉树,对任意结点i(1<=i<=n)
●i=1时,i是二叉树的根,无双亲;i>1时,双亲是[i/2]
●2i>n时,结点无左孩子;2i<=n时,左孩子为2i
●2i+1>n时,结点无右孩子,2i+1<=n时,右孩子为2i+1
二叉树的储存结构
- 顺序储存结构:先补齐为完全二叉树,然后用数组按层储存。
- 链式储存结构:二叉树链表存储的数据类型定义。
二叉树的遍历和线索化
●二叉树的遍历和树的高度计算
#include <stdio.h>
#include <stdlib.h>
//二叉树类型定义
typedef struct btnode
{
int data;
struct btnode *lchild,*rchild;
}btnode,*btree;
//建立二叉树
btnode *createtree()
{
btree t;
char p;
p=getchar();
if (p=='#')
t=NULL;
else
{
t=(btree)malloc(sizeof(btnode));
t->data=p;
t->lchild=createtree();
t->rchild=createtree();
}
return t;
}
//按先序遍历
void preorder(btree root)
{
if (root!=NULL)
{
printf("%c",root->data);
preorder(root->lchild);
preorder(root->rchild);
}
}
//按中序遍历
void inorder(btree root)
{
if (root!=NULL)
{
inorder(root->lchild);
printf("%c",root->data);
inorder(root->rchild);
}
}
//按后序遍历
void postorder(btree root)
{
if (root!=NULL)
{
postorder(root->lchild);
postorder(root->rchild);
printf ("%c",root->data);
}
}
//计算二叉树的高度
int depth(btree t)
{
if (t==NULL)
return 0;
else
{
int h1,h2,h;
h1=depth(t->lchild);
h2=depth(t->rchild);
if (h1>h2)
h=h1+1;
else
h=h2+1;
return h;
}
}
//主函数
int main()
{
btree t;
t=createtree();
printf("输入二叉树的先序排列(空的地方输入#):");
printf("按先序遍历二叉树\n");
preorder(t);
printf ("\n");
printf("按中序遍历二叉树\n");
inorder(t);
printf ("\n");
printf("按后序遍历二叉树\n");
postorder(t);
printf ("\n");
printf ("树的深度\n");
printf ("%d\n",depth(t));
return 0;
}
线索二叉树
根据先根遍历和中根遍历画树
第七章 图
图的邻接表存储及遍历
#include<stdio.h>
#include<stdlib.h>
#define MAX 20
typedef int VexType;
typedef struct Vnode
{
VexType data;
struct Vnode * next;
}Vnode;
typedef Vnode Lgraph[MAX];
typedef struct{
int V[MAX];
int front;int rear;
}Queue;
/* 函数原型声明确规定*/
void creat_L(Lgraph G);
void output_L(Lgraph G);
void dfsL(Lgraph G,int v);
void bfsL(Lgraph G,int v);
Lgraph Ga;
int n,e,visited[MAX];
/*主函数,此部分代码要求手工输入*/
int main()
{
int v1,i;
for(i=0;i<MAX;i++) visited[i]=0;
creat_L(Ga);
output_L(Ga);
printf("please enter the start vex in depth first search:\n");
scanf("%d",&v1);
printf("the result of the depth first search:\n");
dfsL(Ga,v1);
for(i=0;i<MAX;i++) visited[i]=0;
printf("\nplease enter the start vex in breadth first search:\n");
scanf("%d",&v1);
printf("\nthe result of the breadth first search:\n");
bfsL(Ga,v1);
}
/*建立无向图的邻接表,此部分代码要求手工输入*/
void creat_L(Lgraph G)
{
Vnode *p,*q;
int i,j,k;
printf("\nplease enter the number of the vex and edge\n");
scanf("%d,%d",&n,&e);
for(i=1;i<=n;i++){G[i].data=i;G[i].next=NULL;}
for(k=1;k<=e;k++)
{
printf("please enter each edge just like 1,2\n");
scanf("%d,%d",&i,&j);
p=(Vnode *)malloc(sizeof(Vnode));
p->data=i;
p->next=G[j].next;
G[j].next=p ; /*p结点链接到第j条链*/
q=(Vnode *)malloc(sizeof(Vnode));
q->data=j;
q->next=G[i].next;
G[i].next=q ; /*q结点链接到第i条链*/
}
}
/*邻接表的输出,此部分代码要求手工输入*/
void output_L(Lgraph G)
{
int i;
Vnode *p;
for(i=1;i<=n;i++)
{
printf("\nthe vertics which related to[%d] is:",i);
p=G[i].next;
while(p!=NULL){printf("%5d",p->data); p=p->next ;}
}
}
/*初始化队列*/
void initqueue(Queue *q)
{
q->front=-1;
q->rear=-1;
}
/*判断队列是否为空*/
int quempty(Queue *q)
{
if( q->rear==q->front)
return 1;
else
return 0;
}
/*入队操作*/
void enqueue(Queue *q,int e)
{
if( (q->rear+1)%MAX==q->front)
printf("queue is full\n");
else
{
q->rear=(q->rear+1)%MAX;
q->V[q->rear]=e;
}
}
/*出队操作*/
int dequeue(Queue *q)
{
int t;
if(q->front==q->rear)
{printf("queue is empty\n");return 0;}
else
{
q->front=(q->front+1)%MAX;
t=q->V[q->front];
return t;
}
}
/*深度优先遍历图,此部分代码要求手工输入*/
void dfsL(Lgraph G,int v)
{
Vnode *p;
printf("%d->",G[v].data);
visited[v]=1;
p=G[v].next;
while(p){v=p->data;if(visited[v]==0)dfsL(G,v);p=p->next;}
}
/*广度优先遍历图,此部分代码要求手工输入*/
void bfsL(Lgraph g,int v)
{
int x;
Vnode *p;
Queue *q=(Queue *)malloc(sizeof(Queue));
initqueue(q);
printf("\n%d->",g[v].data);
visited[v]=1;
enqueue(q,v);
while(!quempty(q))
{
x=dequeue(q);
p=g[x].next;
while(p){v=p->data;
if(visited[v]==0)
{
printf("%d->",g[v].data);
visited[v]=1;
enqueue(q,v);
}
p=p->next;
}
}
printf("\n");
}
第八章 查找
#include<stdio.h>
void bublesort(int a[10])
{
int i,j,exchange,temp;
for(i=0;i<10;i++)
{
exchange=0;
for(j=9;j>=i;j--)
if(a[j+1]<a[j]){
temp=a[j+1];
a[j+1]=a[j];
a[j]=temp;
exchange=1;
}
if(!exchange)
break;
}
}
//void insertsort(int a[10])
//
//{
//
//int i,j,temp;
//
//for(i=1;i<10;i++)
//
//{
//
// temp=a[i];j=i-1;
//
// while(a[j]>temp && j>=0)
//
// {a[j+1]=a[j];j--;}
//
// a[j+1]=temp ;
//
// }
//
// }
int binsearch(int a[10],int k)
{
int low,high,mid;
low=0;high=9;
while(low<=high)
{
mid= (low+high)/2 ;
if(a[mid]==k) return mid;
if(a[mid]>k) high=mid-1 ;
else low=mid+1 ;
}
return -1;
}
int seqsearch(int a[10],int key)
{
int i;
for(i=0;i<10;i++)
if(key==a[i]) return i;
if(i==10) return -1;
}
main()
{
int key,pos,i;
int a[10]={34,87,23,15,32,46,67,62,28,30};
for(i=0;i<10;i++)
printf("%5d",a[i]);
printf("\nplease enter the key which you want to find");
scanf("%d",&key);
pos=seqsearch(a,key);
printf("the position of the %d is %d\n",key,pos);
bublesort(a);
// insertsort(a);
printf("after sort:\n");
for(i=0;i<10;i++)
printf("%5d",a[i]);
printf("\nplease enter the key which you want to find");
scanf("%d",&key);
pos=binsearch(a,key);
printf("the position of the %d is %d\n",key,pos);
getch();
}
第九章 排序
—插入排序
简单插入排序
#include<stdio.h>
#define n 9
typedef int KeyType;
typedef char OtherType;
typedef struct
{
KeyType key;
OtherType ch[2];
}RecType;
typedef RecType SeqList[n+1];//数组可以容纳10个元素,下面只赋值了9个,R[9].key默认为0,R[9].ch默认为空
//简单插入排序
void InsertSort(SeqList R)
{
int i,j;
for(i=2;i<=n;i++) //从第2个元素遍历到第n个元素
{
R[0]=R[i]; //将第i个元素给哨兵R[0]
for(j=i-1;R[0].key<R[j].key;j--) //若i元素前面一个元素大于哨兵R[0](即i元素)
R[j+1]=R[j]; //则将i前面的元素i-1后移覆盖i元素
R[j+1]=R[0]; //当i元素前面没有比i元素还小的元素时,将R[0]赋值给j+1个元素(即i前面的元素)
}
}
int main(){
SeqList R={{},{14,"A"},{6,"6"},{3,"3"},{5,"5"},{12,"Q"},{10,"10"},{11,"J"},{13,"K"}};//{}为哨兵
int i;
InsertSort(R);
for(i=2;i<=n;i++)//从2开始遍历,因为0位置为哨兵元素,1位置被哨兵元素覆盖为默认值0
printf("%3s(%d)",R[i].ch,R[i].key);
}
输出:
>> 3(3) 5(5) 6(6) 10(10) J(11) Q(12) K(13) A(14)
希尔排序
—交换排序
冒泡排序
快速排序
—选择排序
直接选择排序
堆排序