**数据结构**
1、**线性结构**
1.1 线性表
1.2 堆栈
1.3 队列
2、**树**
2.1 二叉树
2.2 二叉搜索树/二叉查找树
2.3 平衡二叉树
2.4 树的应用
2.4.1 堆
2.4.2 哈夫曼树
2.4.3 集合
3、**散列查找**
4、**图**
5、**排序**
1.1 线性表
顺序存储
顺序表类型:
typedef int Position;
typedef struct LNode * PtrToLNode;
struct LNode
{
ElementType Data[MAXSIZE];
Position Last;
};
typedef PtrToLNode List;
顺序表的初始化建造一个空表
List MakeEmpty()
{
List L;
L = (List)malloc(sizeof(struct LNode));
// for(int i=0;i<n;i++)
// L->Data[i]=a[i];
// L->Last = n;
L->Last = -1;
return L;
}
顺序表的查找:
#define ERROR -1
Position Find(List L, ElementType X)
{
Position i=0;
while(i<=L->Last && L->Data[i]!=X) //Last指向最后一个元素
i++;
if(i>L->Last)
return ERROR;
else
return i; //找到返回对应下标
}
顺序表的插入:
bool Insert(List L, ElementType X, int i)
{
Position j;
if(L->Last == MAXSIZE-1)
{
printf("表满\n");
return false;
}
if(i<1 || i>L->Last+2)
{
printf("位序不合法\n");
return false;
}
for(j=L->Last;j>=i-1;j--)
//从最后的元素开始查找,第i个位置下标是i-1
L->Data[j+1] = L->Data[j];
L->Data[i-1] = X;//第i个位置的数为插入的数据
L->Last++;//更新Last
return true;
}
顺序表的删除:
bool Delete(List L, int i)
{
Position j;
if(i<1 || i>L->Last+1)
{
printf("位序%d不存在元素\n",i);
return false;
}
for(j=i; j<=L->Last ;j++)
//j从第i个元素的后一位开始指
L->Data[j-1] = L->Data[j];
L->Last--;//更新Last
return true;
}
链式表的结构定义:
typedef struct LNode * PtrToLNode;
struct LNode
{
ElementType Data;
PtrToLNode Next;
};
typedef PtrToLNode Position;
typedef PtrToLNode List;
链式表求表长
int Length(List L)
{
Position p;
int cnt = 0;
p = L;//p指向表的第一个结点
while(p)
{
p = p->Next ;
cnt++;
}
return cnt;
}
链式表的按序号查找:
#define ERROR -1
ElementType FindKth(List L, int K)
{
Position p;
int cnt = 1;//从位序1开始
p = L;//p指向L的第一个结点
while(p && cnt<K)
{
p = p->Next ;
cnt++;
}
if((cnt == K) && p)
return p->Data ;//找到第K个元素
else
return ERROR;
}
链式表的按值查找:
#define ERROR NULL
Position Find(List L, ElementType X)
{
Position p = L;//p指向L的第一个结点
while(p && p->Data != X)
p = p->Next ;
//在没找到X且在链尾之前 就一直往下找
if(p)
return p;
else
return ERROR;
}
链式表的插入:
#define ERROR NULL
List Insert(List L, ElementType X, int i)
{
Position tmp , pre;
//分配空间,存入X
tmp = (Position)malloc(sizeof(struct LNode));
tmp->Data = X;
if(i == 1)//在表头插入
{
tmp->Next = L;
return tmp;
}
else
{
int cnt = 1;
pre = L;//pre指向L的第一个结点
while( pre && cnt<i-1 )
{
pre = pre->Next ;
cnt++;
}
if(pre == NULL || cnt!=i-1)
{//没找到,找到链尾了 或者是 不是因为cnt==i-1结束的循环
printf("插入位置参数错误\n");
free(tmp);
return ERROR;
}
else
{//找到了pre
tmp->Next = pre->Next ;
pre->Next = tmp;
return L;
}
}
}
带头结点的链式表的插入:
bool Insert(List L, ElementType X, int i)
{
Position tmp , pre;
int cnt = 0;//有头结点的时候
pre = L;//pre指向表头
while(pre && cnt<i-1)//第i个位置的前一个结点i-1
{
pre = pre->Next ;
cnt++;
}
if(pre == NULL || cnt!=i-1)
{//没找到,找到链尾了 或者是 不是因为cnt==i-1结束的循环
printf("插入位置参数错误\n");
return false;
}
else
{
//找到了待插结点的前一个结点pre,若i==1,pre就指向表头
tmp = (Position)malloc(sizeof(struct LNode));
tmp->Data = X;
tmp->Next = pre->Next ;
pre->Next = tmp;
return true;
}
}
带头结点的链式表的删除:
bool Delete(List L, int i)
{
Position pre;
int cnt = 0;
pre = L;//pre指向表头
while(pre && cnt<i-1)
{
pre = pre->Next ;
cnt++;
}
if(pre==NULL || cnt!=i-1 || pre->Next == NULL)
{// pre->Next == NULL !!!
//所找结点或位序为i的结点不再L中
printf("删除位置参数错误\n");
return false;
}
else
{
pre->Next = pre->Next->Next ;
//课本用了一个中间量tmp
return true;
}
}
1.2 堆栈 先进后出
顺序栈类型:
typedef int Position;
typedef struct SNode * PtrToSNode;
struct SNode
{
ElementType *Data;//存储元素的数组
Position Top;//栈顶指针
int MaxSize;//堆栈最大容量
};
typedef PtrToSNode Stack;
顺序栈的创建:
Stack CreateStack(int MaxSize)
{
Stack S = (Stack)malloc(sizeof(struct SNode));
S->Data = (ElementType*)malloc(MaxSize * sizeof(ElementType));
S->Top = -1;
S->MaxSize = MaxSize;
return S;
}
顺序栈的入栈操作:
bool IsFull(Stack S)
{
return (S->Top == S->MaxSize-1);
}
bool Push(Stack S, ElementType X)
{
if(IsFull(S)) //先判断是否栈满
{
printf("堆栈满\n");
return false;
}
else
{
S->Data[++(S->Top)] = X;
//先++栈顶指针,再赋值
return true;
}
}
顺序栈的出栈操作:
bool IsEmpty(Stack S)
{
return (S->Top == -1);
}
ElementType Pop(Stack S)
{
if(IsEmpty(S))//先判断是否空
{
printf("堆栈空\n");
return ERROR;
//前面得先定义ERROR的值,标志错误
}
else
{
return (S->Data[(S->Top)--]);
//先取数,再栈顶指针--
}
}
链栈的类型:
typedef struct SNode * PtrToSNode;
struct SNode
{
ElementType Data;//存储元素
PtrToSNode Next;
};
typedef PtrToSNode Stack;
带头结点的链栈操作实现:
Stack CreateStack()
{
Stack S;
S = (Stack)malloc(sizeof(struct SNode));
S->Next = NULL;//带头结点
return S;
}
bool Push(Stack S, ElementType X)
{
Stack tmp;
tmp = (Stack)malloc(sizeof(struct SNode));
tmp->Data = X;
tmp->Next = S->Next ;
S->Next = tmp;
//将元素X压入堆栈,头插法
return true;
}
bool IsEmpty(Stack S)
{
return(S->Next == NULL);
}
ElementType Pop(Stack S)
{
Stack First;
ElementType Topelem;//返回删除元素的值
if(IsEmpty(S))
{
printf("堆栈空\n");
return ERROR;
}
else
{
First = S->Next ;
//S指向的是头结点,First指向S的下一个结点
Topelem = First->Data ;
//存下First指向的结点的数据
S->Next = S->Next->Next ;
free(First);
return Topelem;
}
}
1.3 队列 先进先出
队列的顺序存储结构定义:
typedef int ElementType;
typedef int Position;
typedef struct QNode * PtrToQNode;
struct QNode
{
ElementType *Data;
Position Front,Rear;
int MaxSize;
};
typedef PtrToQNode Queue;
循环队列的创建:
Queue CreateQueue(int MaxSize) //创建
{
Queue Q = (Queue)malloc(sizeof(struct QNode));
Q->Data=(ElementType)malloc(MaxSize*sizeof(ElementType));
Q->Front = Q->Rear = 0;
Q->MaxSize = MaxSize;
return Q;
}
循环队列的入队:
bool IsFull(Queue Q) //队满
{
return ((Q->Rear+1)%Q->MaxSize==Q->Front);
}
bool AddQ(Queue Q, ElementType X) //入队
{
if(IsFull(Q))
{
printf("队列满\n");
return false;
}
else
{
Q->Rear = (Q->Rear+1) % Q->MaxSize ;
//入队是Rear指针在变
Q->Data[Q->Rear] = X;
return true;
}
}
循环队列的出队:
typedef -1 ERROR;
bool IsEmpty(Queue Q)
{
return (Q->Front==Q->Rear);
}
ElementType DeleteQ(Queue Q) //删除
{
if(IsEmpty(Q))
{
printf("队列空\n");
return ERROR;
}
else
{
Q->Front = (Q->Front+1)%Q->MaxSize ;
//出队是Front指针在变
return Q->Data[Q->Front];
}
}
链式队列的结构定义:
typedef int ElementType;
typedef struct Node * PtrToNode;
struct Node
{
ElementType Data;
PtrToNode Next;
};
typedef int Position;
typedef struct QNode * PtrToQNode;
struct QNode
{
Position Front,Rear;
int MaxSize;
};
typedef PtrToQNode Queue;
链式队列的删除:
bool IsEmpty(Queue Q)
{
return (Q->Front == NULL);
}
ElementType DeleteQ(Queue Q)
{
Position frntc;
ElementType frntelm;
if(IsEmpty(Q))
{
printf("队列空\n");
return ERROR;
}
else
{
frntc = Q->Front ;
if(Q->Front == Q->Rear ) //队列里只有一个元素
Q->Front = Q->Rear = NULL;
else
{
Q->Front = Q->Front->Next ;
}
frntelm = frntc->Data ;
free(frntc);
return frntelm;
}
}
2.1 二叉树
先列一些树的基本术语:
结点的度,树的度
叶结点,父结点,子结点,兄弟结点,祖先结点,子孙结点
结点的层次,树的深度
分支,路径,路径长度
度之和 = 分支数(边数)= 结点数-1
第 i 层的最大结点数 = 2^(i-1)
深度为 k 的二叉树有最大结点总数 2^k-1
二叉树的链表结构:
typedef int ElementType;
typedef struct TNode * Position;
typedef Position BinTree;
struct TNode
{
ElementType Data;
BinTree Left;
BinTree Right;
};
二叉树的中序遍历:
void InoderTraversal(BinTree BT)
{
if(BT)
{
InoderTraversal(BT->Left);
printf("%d",BT->Data);
InoderTraversal(BT->Right);
}
}
先序遍历、后序遍历也很好写,这里就不列了
在这里先记录非递归中序遍历,往后有时间再写吧
二叉树的层序遍历:
void LevelorderTraversal(BinTree BT)
{
Queue Q;
BinTree T;
if(!BT) return ; //空树直接返回
Q=CreateQueue(); //创建空队列
Add(Q,BT);
while(!IsEmpty(Q))
{
T = DeleteQ(Q);
printf("%d",T->Data);
if(T->Left) Add(Q,T->Left);
if(T->Right) Add(Q,T->Right);
}
}
输出结点:
void PreorderPrintLeaves(BinTree BT)
{
if(BT)
{
if(!BT->Left && !BT->Right) //叶结点
printf("%d",BT->Data);
PreorderPrintLeaves(BT->Left);
PreorderPrintLeaves(BT->Right);
}
}
求二叉树的树高:
int GetHeight(BinTree BT)
{
int HL,HR,MaxH;
if(BT)
{
HL = GetHeight(BT->Left);
HR = GetHeight(BT->Right);
MaxH = HL > HR ? HL : HR;
return (MaxH+1);
}
else return 0;
}
用链表的方式实现二叉树的存储和基本操作,包括CreateBinTree()、PreorderTraversal()、InorderTraversal()、PostorderTraversal()等操作。
//用链表的方式实现二叉树的存储和基本操作,
//包括 CreateBinTree()、PreorderTraversal()、InorderTraversal()、PostorderTraversal()等操作。
#include<stdio.h>
#include<stdlib.h>
#define NoInfo '0'
#define QUEUESIZE 50
typedef char ElementType; //字符型数据
typedef struct TNode * Position;
typedef Position BinTree;
struct TNode //树的结构
{
ElementType Data;
BinTree Left;
BinTree Right;
};
BinTree CreateBinTree() //树的创建
{
ElementType Data;
BinTree BT,T;
BinTree DataQueue[QUEUESIZE];//???
int front = 0;
int rear= 0;
int queuel = 0;
scanf("%c",&Data);
if(Data != NoInfo) //根结点的创建
{
BT=(BinTree)malloc(sizeof(struct TNode));
BT->Data = Data;
BT->Left = BT->Right = NULL;
DataQueue[rear] = BT; //
rear = (rear+1) % QUEUESIZE; //更新 rear 的值
queuel++; //队列长度 ++
}
else
{
return NULL;
}
while(queuel > 0) //
{
T = DataQueue[front];
front = (front+1) % QUEUESIZE; //出队
queuel--; //队列长度 --
scanf("%c",&Data); //输入左子树
if(Data == NoInfo)
{
T->Left = NULL;
}
else
{
T->Left = (BinTree)malloc(sizeof(struct TNode));
T->Left->Data = Data;
T->Left->Left = T->Left->Right = NULL;
DataQueue[rear] = T->Left ; //把数据放入
rear=(rear+1) % QUEUESIZE; //更新 rear
queuel++; //队列长度 ++
}
scanf("%c",&Data); //输入右子树
if(Data == NoInfo)
{
T->Right = NULL;
}
else
{
T->Right = (BinTree)malloc(sizeof(struct TNode));
T->Right->Data = Data;
T->Right->Left = T->Right->Right = NULL;
DataQueue[rear] = T->Right ; //
rear=(rear+1) % QUEUESIZE; //
queuel++; //
}
}
return BT;
}
void PreorderTraversal(BinTree BT)
{
if(BT)
{
printf("%c",BT->Data );
PreorderTraversal(BT->Left);
PreorderTraversal(BT->Right);
}
}
void InorderTraversal(BinTree BT)
{
if(BT)
{
InorderTraversal(BT->Left);
printf("%c",BT->Data );
InorderTraversal(BT->Right);
}
}
void PostorderTraversal(BinTree BT)
{
if(BT)
{
PostorderTraversal(BT->Left);
PostorderTraversal(BT->Right);
printf("%c",BT->Data );
}
}
int main()
{
BinTree BT = CreateBinTree();
PreorderTraversal(BT);
printf("\n");
InorderTraversal(BT);
printf("\n");
PostorderTraversal(BT);
return 0;
}
实现二叉搜索树和平衡二叉树的创建、插入和查找操作。
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 50
typedef int ElementType;
typedef struct BSTNode * BST; //搜索树的类型
struct BSTNode //结点定义
{
ElementType Data;
BST Left;
BST Right;
};
BST InsertBST(BST Root, ElementType X)//BST的插入操作
{
if(Root == NULL)
{
Root = (BST)malloc(sizeof(struct BSTNode));
Root->Data = X;
Root->Left = Root->Right = NULL;
}
else
{
if(X < Root->Data ) //左插
{
Root->Left = InsertBST(Root->Left,X);
}
else if(X > Root->Data ) //右插
{
Root->Right = InsertBST(Root->Right,X);
}
}
return Root;
}
int FindBST(BST Root, ElementType X) //查找次数
{
if(Root == NULL)
return 0;
if(X < Root->Data ) //往左找
return 1+FindBST(Root->Left, X);
else if(X > Root->Data ) //往右找
return 1+FindBST(Root->Right, X);
else // X==Root->Data
return 1;
}
typedef struct AVLNode * AVL; //平衡二叉树的类型
struct AVLNode //结点定义
{
ElementType Data;
AVL Left;
AVL Right;
int Height;//树高
};
int GetHeight(AVL Root) //
{
if(Root == NULL)
return 0;
else
return Root->Height; //
}
int Max(int a, int b)
{
return a>b ? a:b ;
}
AVL SingleLeftRotation(AVL A) //左单旋
{
AVL B = A->Left ;
A->Left = B->Right ;
B->Right = A;
A->Height = Max(GetHeight(A->Left),GetHeight(A->Right)) + 1;
B->Height = Max(GetHeight(B->Left),A->Height) + 1;
return B;
}
AVL SingleRightRotation(AVL A) //右单旋
{
AVL B = A->Right ;
A->Right = B->Left ;
B->Left = A;
A->Height = Max(GetHeight(A->Left),GetHeight(A->Right)) + 1;
B->Height = Max(GetHeight(B->Right),A->Height) + 1;
return B;
}
AVL DoubleLeftRightRotation(AVL A)
{
A->Left = SingleRightRotation(A->Left);
return SingleLeftRotation(A);
}
AVL DoubleRightLeftRotation(AVL A)
{
A->Right = SingleRightRotation(A->Right);
return SingleRightRotation(A);
}
AVL InsertAVL(AVL Root, ElementType X) //AVL的插入
{
if(Root == NULL)
{
Root = (AVL)malloc(sizeof(struct AVLNode));
Root->Data = X;
Root->Left = Root->Right = NULL;
Root->Height = 1;
}
else
{
if(X < Root->Data ) //左插
{
Root->Left = InsertAVL(Root->Left,X);
if(GetHeight(Root->Left)-GetHeight(Root->Right)==2) //左插不平衡
{
if(X < Root->Left->Data)
Root = SingleLeftRotation(Root);
else if(X > Root->Left->Data)
Root = DoubleLeftRightRotation(Root);
}
}
else if(X > Root->Data )
{
Root->Right = InsertAVL(Root->Right,X);
if(GetHeight(Root->Right) - GetHeight(Root->Left) == 2)
{
if(X > Root->Right->Data)
Root = SingleRightRotation(Root);
else if(X < Root->Right->Data )
Root = DoubleRightLeftRotation(Root);
}
}
}
Root->Height = Max(GetHeight(Root->Left),GetHeight(Root->Right)) +1; //更新树高
return Root;
}
int FindAVL(AVL Root, ElementType X) //AVL的查找次数
{
int sum = 0;
while(Root)
{
sum++;
if(X < Root->Data )
Root = Root->Left ; //往左找
else if(X > Root->Data )
Root = Root->Right ; //往右找
else
break;
}
return sum;
}
int main()
{
int n,i;
ElementType a[MAXSIZE];
BST BSTRoot=NULL;
AVL AVLRoot=NULL;
int BSTsum = 0;
int AVLsum = 0;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d",&a[i]); //用数组存放输入的数据
BSTRoot = InsertBST(BSTRoot,a[i]);
AVLRoot = InsertAVL(AVLRoot,a[i]);
}
for(i=0;i<n;i++)
{
BSTsum += FindBST(BSTRoot,a[i]);
AVLsum += FindAVL(AVLRoot,a[i]);
}
printf("%d\n%d",BSTsum,AVLsum);
return 0;
}
2.4.1 堆
2.4.2 哈夫曼树
2.4.3 集合