一、线性表

1、顺序存储=============

类型定义:

const Maxsize=100;

typedef struct

{

  DataType data[Maxsize];

  int length;

}SeqList;

SeqList L;


相关操作实现

1)插入

//在顺序表的第i个节点前插入节点值为x新节点

void InsertSeqList(SeqList L,int i,DataType x)

{

    if(L.length==Maxsize) exit "表已满"

if(i<1||i>L.length+1) exit "位置错"

else

for(int j=L.length;j>=i;j--)

{

   L.data[j]=L.data[j-1];

}

L.data[i-1]=x;

L.length++;

}

----------------------------------------

2)删除

void DeleteSeqList(SeqList L,int i)

{

if(i<1||i>L.length) exit "非法位置"

else

for(int j=i;j<L.length;j++)

{

   L.data[j-1]=L.data[j];

}

L.length--;

}


-----------------------------------------

3)定位

//在顺序表中查找值为x的节点序号,找不到返回0

int LocateSeqList(SeqList L,DataType x)

{

    int i=0;

    while(i<L.length && L.data[i] !=x)

    {

        i++;

    }

    if(i<L.length) return i+1;

    else return 0;

}


2、链式存储=============

类型定义:

typedef struct node

{

   DataType data;

   struct node * next;

}Node,*LinkList,

-----------------------------

1)初始化

LinkList InitiateLinkList()

{

   LinkList head;

   head=malloc(sizeof(Node));

   head->next=NULL;

   return head;  

}

-----------------------------

2)求表长

int LengthLinkList(LinkList head)

{

    LinkList p = head;

    int cnt=0;

    while(NULL != p->next)

    {

       p=p->next;

       cnt++;

    }

    return cnt;

}


-----------------------------

3)读表元素

//在链表中找第i个元素的节点,找到返回指向该节点的指针,找不到返回NULL

LinkList GetLinkList(LinkList head,int i)

{

    LinkList p = head->next;

    int c=1;

    while((NULL != p) && (c < i))

    {

       c++;

       p=p->next;

    }

    if(c == i)

    {

retrun p;

    }

    else retrun NULL;

}


-----------------------------

4)定位

//在表head中查找值为x的节点序号,找不到返回0

int LocateLinkList(LinkList head,DateType x)

{

    LinkList p = head->next;

    int c=1;

    while(NULL != p && p->data !=x)

    {

p=p->next;

c++;

    }

    if(NULL != p) return c;

    else return 0;

}




5)插入

//在链表第i个节点前插入新节点数值为x,(指针q指向插入节点的前一个节点,p指向新生成的节点)

void InsertlinkList(LinkList head,int i,DataType x)

{

LinkList * p, *q;

if(1==i) q=head;

else q=GetLinkList(LinkList head,int i-1); //找到第i-1个数据元素结点,单链表插入时必须找到插入节点的前一个节点

if(NULL = q)

{

   exit "找不到合法插入位置"

}

else

{

   p=malloc(sizeof(Node));

   p->data=x; //给新节点赋值

   p->next=q->next;

   q->next=p;


}


}


6)删除

//删除表第i个节点(指针q指向删除节点的前一个节点,p指向删除节点)

void DeletelinkList(LinkList head,int i)

{

LinkList * p, *q;

if(1==i) q=head;

else q=GetLinkList(LinkList head,int i-1); //找到第i-1个数据元素结点

if(NULL != q && NULL != q->next)

{

   p=q->next;

   q->next=p->next;

   free(p);

}

else 

 exit "删除的节点不存在"

}





建表操作(三种方法)

方法一:


方法二:

//尾插法,每次向表尾插入新的节点,设置指针q一直指向尾节点,设备指针t指向新生成的节点

LinkList CreateLinkList()

{

   Linklist head; //定义头指针变量

   Node *q,*t;

   int x;

   head = malloc(sizeof(Node));//生成头节点

   q=head;   //尾指针首先指向头节点

   scanf("%d",&x); //读取第一个元素

   while(x !=0)

   {

      t=malloc(sizeof(Node));

      t->data=x;

      q->next=t;

      q=t;           //修改尾指针,让其指向新的尾节点

      scanf("%d",&x); //读取新的元素

   }

   q->next = NULL;

   return head;

   

}


方法三:

//头插法,每次向表头插入新的节点,设置指针p指向新生成的节点

LinkList CreateLinkList()

{

   Linklist head; //定义头指针变量

   Node *p;

   int x;

   head = malloc(sizeof(Node));//生成头节点

   head->next=NULL; //初始时,首节点为空

   scanf("%d",&x); //读取第一个元素

   while(x)

   {

      p=malloc(sizeof(Node));

      p->data = x;

      p->next=head->next;  //第一个加入的节点将成为尾节点q->next=NULL;

      head->next=q;

      scanf("%d",&x); //读取新的元素

   }

   return head;

   

}


3、循环链表

1)删除

2)插入


----------------------------

----------------------------

//将一个带头结点的链表逆转

LinkList * reverse(LinkList *L)

{

LinkList * p,*q;

p=L->next;

L->next=NULL;

while(p!=NULL)

{

q=p;

p=p->next;

q->next=L->next; //用头插入法

L->next=q;

}

retrun L;

}


----------------------------

----------------------------

//计算头指针为head的单链表中值为X的个数

int count(LinkList head,DataType x)

{

int cnt = 0;

LinkList p = head;

while(NULL!=p)

{

if(x==p->data)

cnt++;

p=p->next;

}

retrun cnt;

}





二、栈、队列、数组

(一)栈,一种运算受限的线性表,操作只能在表的一端,具有先进后出的特点

======================================================

顺序实现:

数据类型定义:

const init maxsize=10;

typedef struct seqstack;

{

    DataTye data[maxisze];

    int top                 //标识栈顶位置的变量

}SeqStk;


基本运算如下:

1、初始化

int InitStack(SeqStk * stk)

{

    stk->top=0;

    return 1;

}


2、判断空

int EmptyStack(SeqStk * stk)

{

    if(stk->top==0);

    return 1;

    else return 0;

}


3、进栈

int PushStack(SeqStk * stk,DataType x)

{

    if(stk->top==maxsize-1);

    {

       error("栈已满") return 0;

    }

    else

    {

       stk->top++;

       stk->data[stk-top]=x;

        return 1;

    }

    return 1;

}

4、出栈

int PopStack(SeqStk * stk)

{

    if(EmptyStack(stk))

    {

       error("下溢") return 0;

    }

    else 

    {

       stk->top--;

       return 1

    }

}


5、取元素

int GetStack(SeqStk * stk)

{

   if(EmptyStack(stk))

   {

      retrun NULLdata;

   }

   else

   {

      return stk->data[stk->top];

   }

}




====================================

链式实现

数据类型定义:

typedef struck node

{

   DataType data;

   struck node * next;

}LkStk;

//链栈可以用一个带头结点的链表来实现


基本运算:

1、初始化

void InitStack(LKStk * LS)

{

   LS=(LKStk *)malloc(sizeof(LKStk));  //生成头节点

   LS->next=NULL;                      //头节点NEXT为空

}


2、判断空

int EmptyStack(LKStk * LS)

{

    if(LS->next=NULL);

    return 1;

    else return 0;

}



3、进栈

void PushStck(LKStk * LS,DataType x)

{

   LKSst * temp;

   temp=(LKStk *)malloc(sizeof(LKStk));

   temp->data=x;

   temp->next=LS->next;

   LS-next=temp;

}




4、出栈

int PopStck(LKStk * LS)

{

   if(!EmptyStack)

   {

      LKStk * temp;

      temp=LS->next;

      LS-next=temp-next;

      free(temp);

      return 1

   }

   else return 0

}



5、取栈顶元素

DateType GetTop(LKStk * LS)

{

   if(!EmptyStack)

   {

       return LS->next->data;

   }

   else return NULLdata;

}





(2)队列

顺序实现,它由一个一维数组及两个分别指示队列首和队列尾的变量组成,

两个变量分别称为“队列首指针”和“队列尾指针”

循环队列数据类型定义:

const int maxsize=6;

typedef struck cycqueue

{

   DataType data[maxsize];

   int front,rear;

}Cycque;

Cycque CQ;


循环队列满条件:(CQ.rear+1)%maxsize == CQ.front

循环队列空条件:CQ.rear == CQ.front


循环队列的设计,利用模运算

入队:rear=(rear+1)%maxsize

出队:front=(front+1)%maxsize


基本运算:

1、初始化

void Initcycqueue(Cycque CQ)

{

   CQ.front=0

   CQ.rear=0

}


2、判断空

int Emptyqueue(Cycque CQ)

{

   if(CQ.rear == CQ.front)

   return 1;

   else return 0;

}



3、入队列

int Enqueue(Cycque CQ,DataType x)

{

   if((CQ.rear+1)%maxsize == CQ.front)

   {

      error("队列满");return 0;

   }

   else

   {

      CQ.rear=(CQ.rear+1)%maxsize;

      CQ.data[CQ.rear]=x;

      return 1;

   }

}




4、出队列

int Outqueue(Cycque CQ)

{

   if(Emptyqueue(CQ))

   {

      error("队列空");return 0;

   }

   else

   {

      CQ.front=(CQ.front+1)%maxsize;

      return 1;

    }

}




5、取队列首元素

DataType Gethead(Cycque CQ)

{

   if(Emptyqueue(CQ))

   {

      return NULLdata;

   }

   else

   {

      return CQ.data[(CQ.front+1)%maxsize];

     

    }

}


=====================================

队列的链接实现

//用一个带头结点的链表来表示队列,称为链队列

//头指针指向头结点,头结点的next指向首结点,尾指针指向队列尾结点

数据类型定义:

typedef struct LinkQueueNode

{

    DataType data;

    struck LinkQueueNode * next;

}LkQueNode;


typedef struct LKQueue

{

    LkQueNode *front *rear;

}LKQue;

LKQue LQ;


基本运算:

1、队列初始化

void InitQueue(LKQue LQ)

{

   LKQueNode *temp;

   temp = (LKQueNode *)malloc(sizeof(LkQueNode))

   LQ->front = temp;

   LQ->rear = temp;

   LQ->rear->next = NULL;

}



2、判断空

int Emptyqueue(LKQue LQ)

{

   if(CQ->rear == CQ->front)

   return 1;

   else return 0;

}



3、入队列

void Enqueue(LKQue LQ,DataType x)

{

     LKQueNode * temp;   

     temp = (LkQueNode *)malloc(sizeof(LkQueNode));

temp->data=x;

temp->next=NULL;

(LQ->rear)->next=temp;

LQ->rear=temp;

 

}



4、出队列

int Outqueue(LKQue LQ)

{

    LKQueNode * temp;

    if(Emptyqueue(LQ))

{

 error("队列空")

 return 0;

}

else

{  

          temp = (LQ->front)->next; //使temp指向队列的首节点

 LQ->front->next=temp->next;//使头结点指针指向新的首结点

 if(temp->next==NULL) 

 LQ->front=LQ->rear;  //无首节点时

 free(temp);

 return 1;

}

}



5、取队列首元素

DataTye Getqueue(LKQue LQ)

{

  LKQueNode * temp;

  if(Emptyqueue(LQ))

{

 return NULLdata;

}

else

{

 temp=LQ.front->next;

 return temp->data;

}

}




三、树和二叉树

1)基本概念:

结点的度:树上任一结点拥有的子树的数目称为该结点的度。

树的度:一棵树中所有结点的度的最大值称该结的度。

结点的层次:从根开始算起,根的层次为1,其余结点的层次为其双亲的层次加1.

树的高度:一棵树中所有结点层次数的最大值为该树的高度或深度。



二叉树的性质:

1.二叉树的第i层上至多有2 i-1个结点

2.深度为K的二叉树至多有2的K次方-1个结点

3.叶子结点n0,度为2的结点为n2,则n0=n2+1

4.n个结点的完全二叉绔的深度为


二叉对的存储结构:

1、




2、链式存储结构


二叉树的数据类型定义:

typedef struct btnode

{

   DataType data;

   struct btnode lchild,*rchild;

}*BinTree;



2)二叉树的遍历

2.1)二叉树遍历的递归实现

2.1.1)先序遍历

void perorder(BinTree bt)

{

   if(bt!=NULL)

   {

      visit(bt);

      perorder(bt->lchild);

      perorder(bt->rchild);

   }

}



2.1.2)中序遍历

void inorder(BinTree bt)

{

   if(bt!=NULL)

   {

      inorder(bt->lchild);

      visit(bt);

      inorder(bt->rchild);

   }

}




2.1.3)后序遍历

void postorder(BinTree bt)

{

   if(bt!=NULL)

   {

      postorder(bt->lchild);

      postorder(bt->rchild);

      visit(bt);

   }

}

2.2)二叉树的层次遍历

思路:利用一个队列,首先将根(头指针)入队列,以后若队列不空则取队头元素p,

如果p不空,则访问之,然后将其左右子树入队列,如此循环直到队列为空。

void Levelorder(BinTree bt)

{

   InitQueue(Q)   // 队列初始化为空

   Enqueue(Q,bt)  //根入队列

   while(!Emptyqueue(Q))  //队列不空则继续遍历

   {

      Getqueue(Q,bt);  //取队头元素

 if(NULL !=p)

 {

    visit(p->data);

Enqueue(Q,p->lchild) //左右子树入队

Enqueue(Q,p->rchild;

 }

   }

}


2.3)二叉树遍历的非递归实现


一般借助栈实现。设想一指针沿二叉树 中序遍历顺序移动,每当向上层移动时就要出栈。

中序非递归遍历最最重要,后面的两个用于提高。(a)中序非递归遍历 指针p从根开始,

首先沿着左子树向下移动,同时入栈保存;当到达空子树后需要退栈访问结点,

然后移动到右子树上去。




树和森林

一).树的存储结构

1.孩子表示法


2.孩子兄弟链表表示法



3.双亲表示法




四、图





五、查找




六、排序