【数据结构与算法分析】笔记

1 引论

递归的两个基本法则:

  1. 基准情形:你必须总要有某些基准情形,它们不用递归就能求解。
  2. 不断推进:对于那些需要递归求解的情形,递归调用必须总能够朝着产生基准情形的方向推进。

2 算法分析

2.1 最大子序列和问题

//最大子序列和问题
int MaxSubsequenceSum(const int A[],int N){
    int MaxSum=0;
    int ThisSum=0;
    for(int j=0;j<N;j++){
        ThisSum+=A[j];
        if(ThisSum>MaxSum)MaxSum=ThisSum;
        else if(ThisSum<0)ThisSum=0;
    }
    return MaxSum;
}

2.1 判断偶数

//判断偶数
bool IsEven(int x){
    return (x+1)%2;
}

2.2 高效率的取幂运算

//高效率的取幂运算
bool IsEven(unsigned int N){
    return (N+1)%2;
}
long int Pow(const long int X,unsigned N){
    if(N==0)return 0;
    if(N==1)return X;
    if(IsEven(N))return Pow(X*X,N/2);
    else return Pow(X*X,N/2)*X;
    }
}

2.3 求大于某数的下一个素数

static int NextPrime (int N) {
    if (N % 2 == 0)
        ++N;
    int i;
    for (; ; N += 2){
        for (i = 3; i*i <= N; i+=2)
            if (N % i == 0)
                goto ContOuter;
            return N;
        ContOuter:;
    }
}

不使用goto语句

static int NextPrime (int N) {
    if (N % 2 == 0)
        ++N;
    int i;
    bool NotPrime = false;
    for (; ; N += 2){
        NotPrime = true;
        for (i = 3; i*i <= N; i+=2)
            if (N % i == 0) {
                NotPrime = true;
                break;
            }
        if (!NotPrime)
            return N;
    }
}

2.4 isPrime

static int isPrime(int num) {
	for (int i = 2; i <= sqrt(num); i++)
		if (num % i == 0)
			return 0;
	return 1;
}

2.5 大数相加

#include <stdio.h>
#include <string.h>
const int maxn = 2000;
int arr[maxn];
char str1[maxn], str2[maxn];

int jiafa(int len1, int len2)
{
    int sum = 0;
    while (len1 > 0 && len2 > 0) {
        arr[sum] = (str1[--len1] - '0') + (str2[--len2] - '0') + arr[sum];
        arr[sum + 1] = arr[sum] / 10;
        arr[sum] %= 10;
        sum++;
    }
    while (len1 > 0) {
        arr[sum] = (str1[--len1] - '0') + arr[sum];
        arr[sum + 1] = arr[sum] / 10;
        arr[sum] %= 10;
        sum++;
    }
    while (len2 > 0) {
        arr[sum] = (str2[--len2] - '0') + arr[sum];
        arr[sum + 1] = arr[sum] / 10;
        arr[sum] %= 10;
        sum++;
    }
    if (arr[sum] != 0)
        return sum;
    else
        return (sum - 1);
}
int main()
{
    int n;
    scanf("%d", &n);
    for (int p = 1; p <= n; p++) {
        memset(arr, 0, sizeof(arr));
        memset(str1, 0, sizeof(str1));
        memset(str2, 0, sizeof(str2));

        scanf("%s %s", str1, str2);

        int len1 = strlen(str1);
        int len2 = strlen(str2);
        int lrh = jiafa(len1, len2);

        printf("Case %d:\n", p);
        printf("%s + %s = ", str1, str2);
        for (int i = lrh; i >= 0; i--)
            printf("%d", arr[i]);
        printf("\n");
        if (p != n)
            printf("\n");
    }
    return 0;
}

2.6快速幂

int poww(int a,int b){
    int ans=1,base=a;
    while(b!=0){
        if(b&1!=0)ans*=base;
        base*=base;
        b>>=1;
   }
    return ans;
}

3 表、栈和队列

抽象数据类型ADT(abstract datad type)

全局变量和副作用是有害的观念正是出于模块化是有益的想法。

3.1 单向链表

有些编程人员发现递归地编写Find例程颇有吸引力,大概是因为这样可能避免冗长的终止条件。后面将看到,这是一个非常糟糕的想法,我们要不惜一切代价避免它。

//单向链表
//头文件
#pragma once
#ifndef _List_H

struct Node;

typedef struct Node* PtrToNode;
typedef PtrToNode List;                //struct Node*
typedef PtrToNode Position;

List MakeEmpty(List L);
int IsEmpty(List L);
int IsLast(Position P, List L);
Position Find(int X, List L);

void Delete(int X, List L);

Position FindPrevious(int X, List L);

void Insert(int X, List L, Position P);
void DeleteList(List L);
Position Header(List L);
Position First(List L);
Position Advance(Position P);
int Retrieve(Position P);
#endif    /* _List_H */

/* Place in the implementation file*/
struct Node {
	int Element;
	Position Next;
};
//源文件
void IsEmpty(List L){
    return L->Next==NULL;
}
void IsLast(Position P,List L){
    return P->Next==NULL;
}
Position Find(int X,List L){
    Position P;
    P=L;
    while(P->Next!=NULL&&P->Element!=X)
        P=P->Next;
    return P;
}
Position FindPrevious(int X,List L){
    Position P;
    P=L;
    while(P->Next!=NULL&&P->Next->Element!=X)
        P=P->Next;
    return P;
}
void Delete(int X,List L){
    Position P,TemCell;
    P=FindPrevious(X,L);
    if(!IsLast(P)){
       TemCell=P->Next;
        P->Next=TemCell->Next;
        free(TemCell);
    }  
}
void Insert(int X,List L,Position P){
    Position TemCell;
    TemCell=(Node*)malloc(sizeof(Node));
    if(TemCell==NULL)
        printf("FatalError:out of space!!!");
    TemCell->Element=X;
    TemCell->Next=P->Next;
    P->Next=TemCell;
}
void DeleteList(List L){
    Position P,TemCell;
    P=L;
    while(P!=NULL){
        TemCell=P->Next;
        free(P);
        P=TemCell;
    }
}

3.2 链表游标

//链表游标
#pragma once
#ifndef _Cursor_H

struct Node;
typedef struct Node* PtrToNode;
typedef PtrToNode List;
typedef PtrToNode Position;

void InitializeCursorSpace(void);

List MakeEmptyr(List L);
int IsEmpty(const List L);
int IsLast(const Position P, const List L);
Position Find(int X, const List L);
void Delente(int X, List L);
Position FindPrevious(int X, const List L);
void Insert(int X, List L, Position P);
void DeleteList(List L);
Position Header(const List L);
Position First(const List L);
Position Advance(const Position P);
int Retrieve(const Position P);
 
#endif     /*_Cursor_H*/

/*Place in the implementation file*/
struct Node {
	int Element;
	Position Next;
};

struct Node CursorSpace[SpaceSize];

//源文件
//CursorAlloc & CursorFree
static Position CursorAlloc(void) {
	Position P;
	P = CursorSpace[0].Next;
	CursorSpace[0].Next = CursorSpace[P].Next;
	return P;
}
static void CursorFree(Position P) {
	CursorSpace[P].Next = CursorSpace[0].Next;
	CursorSpace[0].Next = P;
}
//测试一个链表是否为空的函数——游标实现
int IsEmpty(List L) {
	return CursorSpace[L].Next == 0;
}
//测试P是否是链表的末尾的函数——游标实现
int IsLast(Position P, List L) {
	return CursorSpace[P].Next == 0;
}
//Find——游标实现
Position Find(int X, List) {
	Position P;
	P = InitializeCursorSpace[L].Next;
	while (P && CursorSpace[P].Element != X)
		P = CursorSpace[P].Next;
	return P;
}
//Delete——游标实现
void Delete(int X, List L) {
	Position P, TmpCell;
	P = FindPrevious(X, L);
	if (!IsLast(P, L)) {
		TmpCell = CursorSpace[P].Next;
		CursorSpace[P].Next = CursorSpace[TmpCell].Next;
		CursorFree(TmpCell);
	}
}
//Insert——游标实现
void Insert(int X, List L, Position P) {
	Position TmpCell;
	TmpCell = CursorAlloc();
	if (TmpCell == 0)
		printf("FatalError:out of space!!!");
	CursorSpace[TmpCell].Element = X;
	CursorSpace[TmpCell].Next = CursorSpace[P].Next;
	CursorSpace[P].Next = TmpCell;
}

3.3 栈——链表实现

//栈 链表实现
//头文件
#ifndef _Stack_h
struct Node;
typedef struct Node* PtrToNode;
typedef PtrToNode Stack;
int IsEmpty(Stack S);
Stack CreateStack(void);
void DisPoseStack(Stack S);
void MakeEmpty(Stack S);
void Push(int X, Stack S);
int Top(Stack S);
void Pop(Stack S);

#endif /* _Stack_h */
 /* Place in implementation file */
/* Stack implementation is a liinked list with a header */
struct Node {
	int Element;
	PtrToNode Next;
};
//
//栈为空——链表实现
int IsEmpty(Stack S) {
	return S->Next == NULL;
}
//创建一个空栈——链表实现
Stack CreateStack(void) {
	Stack S;
	S = (Node*)malloc(sizeof(struct Node));
	if (S == NULL)
		printf("FatalError:out of space!!!");
	S->Next == NULL;
	MakeEmpty(S);
	return S;
}
void MakeEmpty(Stack S) {
	if (S == NULL)
		printf("FatalError:out of space!!!");
	else while (!IsEmpty(S))
		Pop(S);
}
//
void Push(int X, Stack S) {
	PtrToNode TmpCell;
	TmpCell = (Node*)malloc(sizeof(Node*));
	if (TmpCell == NULL)
		printf("FatalError:out of space!!!");
	else {
		TmpCell->Elememt = X;
		TmpCell->Next = S->Next;
		S->Next = TmpCell;
	}
}
//
int Top(Stack S) {
	if (!IsEmpty(S))
		return S->Next->Element;
	printf("Empty stack");
	return 0;
}
//
void Pop(Stack S) {
	PtrToNode FirstCell;
	if (IsEmpty(S))
		printf("Empty stack");
	else {
		FirstCell = S->Next;
		S->Next = S->Next->Next;
		free(FirstCell);
	}
}

3.4 栈——数组实现

栈模型:只有栈顶元素是可访问的。

如果使用好的编程原则,调用例程不必知道使用的是哪种方法。

栈的链表实现:这种实现方法的缺点在于对malloc和free的调用的开销是昂贵的,特别是与指针操作的例程相比尤其如此。

//栈 数组实现
#ifndef _Stack_h

struct StackRecord;
typedef struct StackRecord* Stack;

int IsEmpty(Stack S);
Stack CreateStack(int);
void DisposeStack(Stack S);
void MakeEmpty(Stack S);
void Push(int X, Stack S);
int Top(Stack S);
void Pop(Stack S);
int TopAndPop(Stack S);

#endif                 /* _Stack_h */

/* Place in implementation file */
/* Stack implementation is a dynamically allocated array */
#define EmptyTOS (-1)
#define MinStackSize (5)

struct StackRecord {
	int Capacity;
	int TopOfStick;
	int* Array;
};
//
Stack CreateStack(int MaxElements) {
	Stack S;
	if (MaxElements < MinStackSize)
		printf("Stack size is too small");
	S = (StackRecord*)malloc(sizeof(struct StackRecord));
	if (S == NULL)
		printf("FatalError:out of space!!!");
	S->Array = malloc(sizeof(int) * MaxElements);
	if (S->Array == NULL)
		printf("FatalError:out of space!!!");
	S->Capacity = MaxElements;
	MakeEmpty(S);
	return S;
}
//
void DisposeStack(Stack S) {
	if (S != NULL) {
		free(S->Array);
		free(S);
	}
}
//
int IsEmpty(Stack S) {
	return S->TopOfStack == EmptyTOS;
}
//
void MakeEmpty(Stack S) {
	S->TopOfStack = EmptyTOS;
}
//
void Push(int X, Satck S) {
	if (IsFull(S))
		printf("Full stack");
	else
		S->Array[++S->TopOfStack] = X;
}
//
int Top(Stack S) {
	if (!IsEmpty(S))
		return S->Arrat[S->TopOfStack];
	printf("Empty stack");
	return 0;
}
//
void Pop(Stack S) {
	if (IsEmpty(S))
		printf("Empty stack");
	else
		S->TopOfStack--;
}
//给出栈顶元素并从栈弹出——数组实现
int TopAndPop(Stack S) {
if (!IsEmpty(S))
return S->Array[S->TopOfStack--];
printf("Empty stack");
return 0;
}

3.5 队列——数组实现

//队列的数组实现
//
#ifndef _Queue_h

struct QueueRecord;
typedef struct QueueRecord* Queue;
 
int IsEmpty(QueueRecord Q);
int IsFull(Queue Q);
Queue CreateQueue(int MaxElements);
void DisopseQueue(Queue Q);
void MakeEmpty(Queue Q);
void Enqueue(int X, Queue Q);
int Front(Queue Q);
void Dequeue(Queue Q);
int FrontAndDequeue(Queue Q);

#endif    /* _Queue_h */

/* Place in implementation file */
/* Queue implementation is a dynamically allocated array */
#define MinQueueSize (5)

struct QueueRecord {
	int Capacity;
	int Front;
	int Rear;
	int Size;
	int* Array;
};
//
int IsEmpty(Queue Q) {
	return Q->Size == 0;
}
//
void MakeEmpty(Queue Q) {
	Q->Size = 0;
	Q->Front = 1;
	Q->Rear = 0;
}
//
static int Succ(int Value, Queue Q) {
	if (++Value== Q->Capacity)
		Value = 0;
	return Value;
}
void Enqueue(int X, Queue Q) {
	if (IsFull(Q))
		printf("Full queue");
	else {
		Q->Size++;
		Q->Rear = Succ(Q->Rear, Q);
		Q->Array[Q->Rear] = X;
	}
}

4 树

4.1 树

//树的节点声明
typedef struct TreeNode* PtrToNode;
struct TreeNode {
	int Element;
	PtrToNode FirstChild;
	PtrToNode NextSibling;
};
//列出分级文件系统中目录
static void ListDir(DirectoryOrFile D, int Depth) {
	if (D is a legitimate entry) {
		PrintName(D, Depth);
		if (D si a directory)
			for each child, C, of D
				ListDir(C, Depth + 1);
	}
}
void ListDirectory(DirectoryOrFile D) {
	ListDir(D, 0);
}
//目录(先序)列表
/usr
mark
book
ch1.r
ch2.r
ch3.r
course
cop3530
fall96
syl.r
spr97
syl.r
sum97
syl.r
junk.c
alex
junk.c
bill
work
course
cop3212
fall96
grades
prog1.r
prog2.r
fall97
prog2.r
prog1.r
grades
    //计算一个目录大小
static void SizeDirectory(DirectoryOrFile D) {
	int TotalSize;
	TotalSize = 0;
	if (D ia a legitimate entry) {
		TotalSize = FileSize(D);
		if (D is a directory)
			for (each child, C, of D)
				TotalSize += SizeDirecotry(C);
	}
	return TotalSize;
}

4.2 二叉查找树

//二叉查找树声明
#ifndef _Tree_H

struct TreeNode;
typedef struct TreeNode* Position;
typedef struct TreeNode* SearchTree;

SearchTree MakeEmpty(SearchTree T);
Position Find(int X, SearchTree T);
Position FindMin(SearchTree T);
Position FindMax(SearchTree T);
SearchTree Insert(int X, SearchTree T);
SearchTree Delete(int X, SearchTree T);
int Retrieve(Position P);

#endif  /* _Tree_H */

/* Place in the implementation file */
struct TreeNode {
	int Element;
	SearchTree Left;
	SearchTree Right;

};
//建立一棵空树的例程
SearchTree MakeEmpty(SearchTree T) {
	if (T != NULL) {
		MakeEmpty(T->Left);
		MakeEmpty(T->Right);
		free(T);
	}
	return NULL;
}
//二叉查找树的Find操作
Position Find(int X, SearchTree T) {
	if (T == NULL)
		return NULL;
	if (X < T->Element)
		return Find(X, T->Right);
	else return T;
}
//对二叉查找树的FindMin的递归实现
Position FindMin(SearchTree T) {
	if (T == NULL)
		return NULL;
	else
		if ((T->Left == NULL))
			return T;
		else
			return FindMin(T->Left);
}
//对二叉查找树的FindMax的非递归实现
Position FindMax(SearchTree T) {
	if (T != NULL)
		while (T->Right != NULL)
			T = T->Right;
	return T;
}
//插入元素到二叉查找树的例程
SearchTree Insert(int X, SearchTree T) {
	if (T == NULL) {
		T = (TreeNode*)malloc(sizeof(struct TreeNode));
		if (T == NULL)
			printf("Out of space!!!");
		else {
			T->Element = X;
			T->Left = T->Right = NULL;
		}
	}
	else
		if (X < T->Element)
			T->Left = Insert(X, T->Left);
		else
			if (X > T->Element)
				T->Right = Insert(X, T->Right);
	return T;
}
//二叉查找树的删除例程(返回树根节点)
SearchTree Delete(int X, SearchTree T) {
	Position TmpCell;
	if (T == NULL)
		printf("Element not found");
	else
		if (X < T->Element)
			T->Left = Delete(X, T->Left);
		else
			if (X > T->Element)
				T->Right = Delete(X, T->Right);
			else
				if (T->Left && T->Right) {
					TmpCell = FindMin(T->Right);
					T->Element = TmpCell->Element;
					T->Right = Delete(T->Element,T->Right);
				}
				else {/* One or zero children */
					TmpCell = T;
					if (T->Left == NULL) /* Also handles 0 children */
						T = T->Right;
					else if (T->Right == NULL)
						T = T->Left;
					free(TmpCell);
				}
	return T;
}

4.3 AVL树

#include<stdio.h>
#include<stdlib.h>
#define ElementType int 
#ifndef _AvlTree_H

struct AvlNode;
typedef struct AvlNode* Position;
typedef struct AvlNode* AvlTree;

AvlTree MakeEmpty(AvlTree T);
Position Find(ElementType X, AvlTree T);
Position FindMin(AvlTree T);
Position FindMax(AvlTree T);
AvlTree Insert(ElementType X, AvlTree T);
AvlTree Delete(ElementType X, AvlTree T);
ElementType Retrieve(Position P);

static Position SingleRotateWithLeft(Position k2);
static Position DoubleRotateWithLeft(Position k3);

#endif   /* _AvlTree_H */

/* Place in the implementation file */
struct AvlNode {
	ElementType Element;
	AvlTree Left;
	AvlTree Right;
	int Hight;
};
int Max(int a, int b) {
	if (a > b)return a;
	else return b;
}

//执行单旋转的例程
/* This function can be called only if k2 has a left child */
/* Perform a rotate between a node (k2) and its left child */
/* Update heights,then return new root */
/* 右旋 */
static Position SingleRotateWithLeft(Position k2) {
	Position k1;
	k1 = k2->Left;
	k2->Left = k1->Right;
	k1->Right = k2;
	k2->Hight = Max(Height(k2->Left), Height(k2->Right)) + 1;
	k1->Hight = Max(Height(k1->Left), k2->Hight) + 1;
	return k1;  /* New root */
}
static Position SingleRotateWithRight(Position k2) {
	Position k1;
	k1 = k2->Right;
	k2->Right = k1->Left;
	k1->Left = k2;
	k2->Hight = Max(Height(k2->Left), Height(k2->Right)) + 1;
	k1->Hight = Max(Height(k1->Left), k2->Hight) + 1;
	return k1;  /* New root */
}

//执行双旋转的例程
/* This function can be called only if k3 has a left */
/* child and k3's left child has a right child */
/* Do the left-right double rotation */
/* Update heights,then return new root */
static Position DoubleRotateWithLeft(Position k3) {
	/* Rotate between k1 and k2 */
	k3->Left = SingleRotateWithRight(k3->Left);
	/* Rotate between k3 and k2 */
	return SingleRotateWithLeft(k3);
}

static Position DoubleRotateWithRight(Position k3) {
	/* Rotate between k1 and k2 */
	k3->Right = SingleRotateWithLeft(k3->Right);
	/* Rotate between k3 and k2 */
	return SingleRotateWithRight(k3);
}
//计算AVL节点的高度的函数
static int Height(Position P) {
	if (P == NULL)
		return -1;
	else
		return P->Hight;
}
//向AVL树插入节点的函数
AvlTree Insert(ElementType X, AvlTree T) {
	if (T == NULL) {
		/* Creat and return a one-node tree */
		T = (AvlNode*)malloc(sizeof(struct AvlNode));
		if (T == NULL) {
			printf("out of space!!!");
			return NULL;
		}
		else {
			T->Element = X;
			T->Left = T->Right = NULL;
			T->Hight = 0;
		}
	}
	else
		if (X < T->Element) {
			T->Left = Insert(X, T->Left);
			if (Height(T->Left) - Height(T->Right) == 2)
				if (X < T->Left->Element)
					T = SingleRotateWithLeft(T);
				else
					T = DoubleRotateWithLeft(T);
		}
		else
			if (X > T->Element) {
				T->Right = Insert(X, T->Right);
				if (Height(T->Right) - Height(T->Left) == 2)
					if (X > T->Right->Element)
						T = SingleRotateWithRight(T);
					else
						T = DoubleRotateWithRight(T);
			}
	/* Else X is in the tree already: we'll do nothing */
	T->Hight = Max(Height(T->Left), Height(T->Right)) + 1;
	return T;
}

4.4 树的遍历

//按顺序打印二叉树的例程
void PrintTree(SearchTree T) {
	if (T != NULL) {
		PrintTree(T->Left);
		PrintElement(T->Element);
		PrintTree(T->Right);
	}
}
//使用后序遍历计算树的高度例程
int Height(Tree T) {
	if (T == NULL)
		return -1;
	else
		return 1 + Max(Height(T->Left), Height(T->Right));
}

4.5 B树

5 散列

5.1 散列函数

typedef unsigned int Index;

//一个简单的散列函数
Index Hash(const char* Key, int TableSize) {
	unsigned int HashVal = 0;
	while (*Key != '\0')
		HashVal += *Key++;
	return HashVal % TableSize;
}
//一个好的散列函数
Index Hash(const char* Key, int TableSize) {
	unsigned int HashVal = 0;
	while (*Key != '\0')
		HashVal = (HashVal << 5) + *Key++;
	return HashVal % TableSize;
}

5.2 分离链接散列表

#include<stdio.h>
#include<stdlib.h>

#define ElementType int
//分离链接散列表的类型声明
#ifndef _HashSep_H

struct ListNode;
typedef struct ListNode* Position;
struct HashTbl;
typedef struct HashTbl* HashTable;

HashTable InitialzeTable(int TableSize);
void DestroyTable(HashTable H);
Position Find(ElementType Key, HashTable H);
void Insert(ElementType Key, HashTable H);
ElementType Retrieve(Position P);
/* Routines such as Delete and MakeEmpty are omittd */

#endif   /* HashSep_H */

/* Place in the implementation file */
struct ListNode {
	ElementType Element;
	Position Next;
};

typedef Position List;

/* List *TheList will be an array of listss, allocated later */
/* The lists use headers(for simplicit), */
/* though this wastess space */
struct HashTbl {
	int TableSize;
	List* TheLists;
};
//分离链接散列表的初始化例程
HashTable InitializeTable(int TableSize) {
	HashTable H;
	int i;
	if (TableSize < MinTableSize) {
		printf("Table size too small");
		return NULL;
	}
	/* Allocate table */
	H = (HashTbl*)malloc(sizeof(struct HashTbl));
	if (H == NULL)
		printf("out of space!!!");
	H->TableSize = NextPrime(TableSize);
	/* Allocate array of lists */
	H->TheLists = (List*)malloc(sizeof(List) * H->TableSize);
	if (H->TheLists == NULL)
		printf("out of space!!!");
	/* Allocate list headers */
	for (i = 0; i < H->TableSize; i++) {
		H->TheLists[i] = (ListNode*)malloc(sizeof(struct ListNode));
		if (H->TheLists == NULL)
			printf("out of space!!!");
		else
			H->TheLists[i]->Next = NULL;
	}
	return H;
}
//分离连接散列表的Find例程
Position Find(ElementType Key, HashTable H) {
	Position P;
	List L;
	L = H->TheLists[Hash(Key, H->TableSize)];
	P = L->Next;
	while (P != NULL && P->Element != Key)
		/* Probably need strcmp!! */
		P = P->Next;
	return P;
}
//分离链接散列表的Insert例程
void Insert(ElementType Key, HashTable H) {
	Position Pos, NewCell;
	List L;
	Pos = Find(Key, H);
	if (Pos == NULL)/* Key is not found */
	{
		NewCell = (ListNode*)malloc(sizeof(struct ListNode));
		if (NewCell == NULL)
			printf("out of space!!!");
		else
		{
			L = H->TheLists[Hash(Key, H->TableSize)];
			NewCell->Next = L->Next;
			NewCell->Element = Key;/* Probably need strcpy! */
			L->Next = NewCell;
		}
	}
}

#include <stdio.h>
#include <stdlib.h>

#define Error(Str) FatalError(Str)
#define FatalError(Str) fprintf(stderr, "%s\n", Str), exit(1)

typedef char* ElementType;

#ifndef _HashSep_H

struct ListNode;
typedef struct ListNode* Position;
struct HashTbl;
typedef struct HashTbl* HashTable;

HashTable initializeTable(int tableSize);
void destroyTable(HashTable h);
Position find(ElementType key, HashTable h);
void insert(ElementType key, HashTable h);
void Delete(ElementType key, HashTable h);
ElementType retrive(Position p);

#endif


//#include"fatal.h"
#include<math.h>
#include<string.h>
#define MinTableSize 10

struct ListNode {
	ElementType element;
	Position next;
};

typedef Position List;

struct HashTbl {
	int tableSize;
	List* theLists;//数组指针
};

static int hash(ElementType key, int tableSize) {
	unsigned int hashVal = 0;
	while (*key != '\0')
		hashVal = (hashVal << 5) + *key++;
	return hashVal % (tableSize);
}
static int isPrime(int num) {
	for (int i = 2; i <= sqrt(num); i++)
		if (num % i == 0)
			return 0;
	return 1;
}
static int nextPrime(int num) {
	int i = num;
	while (!isPrime(i))
		i++;
	return i;
}

int NextPrime(int n) {
	if (n % 2 == 0)
		n++;
	while (!isPrime(n))
		n += 2;
	return n;
}

HashTable initializeTable(int tableSize) {
	HashTable h;
	int i;
	if (tableSize < MinTableSize) {
		Error("Table size too small");
		return NULL;
	}
	h = (HashTbl*)malloc(sizeof(struct HashTbl));
	if (h == NULL)
		FatalError("Out of space!!!");
	h->tableSize = nextPrime(tableSize);
	h->theLists =(List*) malloc(sizeof(List) * h->tableSize);
	if (h->theLists == NULL)
		FatalError("Out of space!!!");
	for (i = 0; i < h->tableSize; i++) {
		h->theLists[i] = (List)malloc(sizeof(struct ListNode));
		if (h->theLists == NULL)
			FatalError("Out of space!!!");
		else {
			h->theLists[i]->next = NULL;
		}
	}
	return h;
}


void destroyTable(HashTable h) {
	for (int i = 0; i < h->tableSize; i++) {
		List l = h->theLists[i];
		Position p = l;
		while (p) {
			Position temp;
			temp = p->next;
			free(p);
			p = temp;
		}
	}
	free(h->theLists);
	free(h);
}


Position find(ElementType key, HashTable h) {
	Position p;
	List l;

	l = h->theLists[hash(key, h->tableSize)];

	p = l->next;
	while (p && strcmp(p->element, key) != 0)
		p = p->next;
	return p;
}

void insert(ElementType key, HashTable h) {
	Position pos, newCell;
	List l;

	pos = find(key, h);
	if (pos == NULL) {
		newCell = (ListNode*)malloc(sizeof(struct ListNode));
		if (newCell == NULL)
			FatalError("Out of space!!!");
		newCell->element = (char*)malloc(sizeof(char) * strlen(key) + 1);//+1是为了给\0留空间
		if (newCell->element == NULL)
			FatalError("Out of space!!!");

		l = h->theLists[hash(key, h->tableSize)];
		newCell->next = l->next;
		l->next = newCell;
		strcpy(newCell->element, key);

	}
}

void Delete(ElementType key, HashTable h) {
	Position p;
	List l;

	l = h->theLists[hash(key, h->tableSize)];
	p = l;
	while (p->next && strcmp(p->next->element, key) != 0)
		p = p->next;
	if (p->next) {
		Position deleteCell = p->next;
		p->next = deleteCell->next;
		free(deleteCell->element);
		free(deleteCell);
	}
}

ElementType retrive(Position p) {
	return p->element;
}

/*
int main() {
	HashTable h = initializeTable(500);
	insert("aaaaaaa", h);
	Position p = find("aaaaaaa", h);
	if (p)
		printf("%s", retrive(p));
	Delete("aaaaaaa", h);
	p = find("aaaaaaa", h);
	if (p)
		printf("%s", retrive(p));
	destroyTable(h);
}
*/

5.3 开放定址散列表

#include<stdio.h>
#include<stdlib.h>
#define MinTableSize 5
typedef char* ElementType;

//开放定址散列表声明
#ifndef _HashQuad_H
typedef unsigned int Index;
typedef Index Position;
struct HashTbl;
typedef struct HashTbl* HashTable;

HashTable InitializeTable(int TableSize);
void DestroyTable(HashTable H);
Position Find(ElementType Key, HashTable H);
void Insert(ElementType Key, HashTable H);
ElementType Retrieve(Position P, HashTable H);
HashTable Rehash(HashTable H);
Index Hash(const char* Key, int TableSize);
int NextPrime(int N);
/* Routines such as Delete and MakeEmpty are omitted */

#endif  /* _HahsQuad_H */

/* Place in the implementation file */
enum KindOfEntry { Legitimate, Empty, Deleted };

struct HashEntry {
	ElementType Element;
	enum KindOfEntry Info;
};

typedef struct HashEntry Cell;

/* Cell *TheCells will be an array of */
/* Hash Entry cells,allocated later */
struct HashTbl {
	int TableSize;
	Cell* TheCells;
};
int NextPrime(int N) {
	if (N % 2 == 0)
		++N;
	int i;
	bool NotPrime = false;
	for (; ; N += 2) {
		NotPrime = true;
		for (i = 3; i * i <= N; i += 2)
			if (N % i == 0) {
				NotPrime = true;
				break;
			}
		if (!NotPrime)
			return N;
	}
}

Index Hash(const char* Key, int TableSize) {
	unsigned int HashVal = 0;
	while (*Key != '\0')
		HashVal = (HashVal << 5) + *Key++;
	return HashVal % TableSize;
}

//初始化开放定址散列表的例程
HashTable InitializeTable(int TableSize) {
	HashTable H;
	int i;
	if (TableSize < MinTableSize) {
		printf("Tablee size too small");
		return NULL;
	}
	/* Sllocate table */
	H = (HashTbl*)malloc(sizeof(struct HashTbl));
	if (H == NULL)
		printf("out of space!!!");
	H->TableSize = NextPrime(TableSize);
	/* Allocate array of Cells */
	H->TheCells = (Cell*)malloc(sizeof(Cell) * H->TableSize);
	if (H->TheCells == NULL)
		printf("out of space!!!");
	for (i = 0; i < H->TableSize; i++)
		H->TheCells[i].Info = Empty;
	return H;
}
HashTable in(int TableSize) {
	HashTable H;
	int i;
	H = (HashTable)malloc(sizeof(struct HashTbl));
	if (H == NULL)
		printf("out of space!!!");
	H->TableSize = NextPrime(TableSize);
	H->TheCells = (Cell*)malloc(sizeof(Cell) * TableSize);
	if (H->TheCells == NULL)
		printf("out of space!!!");
	for (i = 0; i < TableSize; i++) {
		H->TheCells[i].Info = Empty;
	}
	return H;
}
//使用平方探测散列法的Find例程
Position Find(ElementType Key, HashTable H) {
	Position CurrentPos;
	int CollisionNum;
	CollisionNum = 0;
	CurrentPos = Hash(Key, H->TableSize);
	while (H->TheCells[CurrentPos].Info != Empty && H->TheCells[CurrentPos].Element != Key)
		/* Probably need strcmp!! */
	{
		CurrentPos += 2 * ++CollisionNum - 1;
		if (CurrentPos >= H->TableSize)
			CurrentPos -= H->TableSize;
	}
	return CurrentPos;
}
//使用平方探测散列表的插入例程
void Insert(ElementType Key, HashTable H) {
	Position Pos;
	Pos = Find(Key, H);
	if (H->TheCells[Pos].Info != Legitimate) {
		/* OK to insert here */
		H->TheCells[Pos].Info = Legitimate;
		H->TheCells[Pos].Element = Key;
		/* Probably need strcpy */
	}
}
//对开放定址散列表的再散列
HashTable Rehash(HashTable H) {
	int i, OldSize;
	Cell* OldCells;
	OldCells = H->TheCells;
	OldSize = H->TableSize;
	/* Get a new, empty table */
	H = InitializeTable(2 * OldSize);
	/* Scan through old table,reiinserting into new */
	for (i = 0; i < OldSize; i++)
		if (OldCells[i].Info == Legitimate)
			Insert(OldCells[i].Element, H);
	free(OldCells);
	return H;
}




6 优先队列(堆)

6.1 二叉堆

因为完全二叉树很有规律,所以它可以用一个数组表示而不需要指针。对于数组中任一位置i上的元素,其左儿子在位置2i上,右儿子(在左儿子后的单元2i+1)中,它的父亲则在位置[i/2]上。

03011222192

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7bk9UI5s-1675990011909)(D:/pictures/3.png)]

#include<stdio.h>
#include<stdlib.h>
#define MinPQSize 5
#define MinData -217
typedef int ElementType;
//优先队列的声明
#ifndef _BinHeap_H

struct HeapStruct;
typedef struct HeapStruct* PriorityQueue;

PriorityQueue Initialize(int MaxElemets);
void Destroy(PriorityQueue H);
void MakeEmpty(PriorityQueue H);
void Insert(ElementType X, PriorityQueue H);
ElementType DeleteMiin(PriorityQueue H);
ElementType FindMin(PriorityQueue H);
int IsEmpty(PriorityQueue H);
int IsFull(PriorityQueue H);

#endif

/* Place in implementation file */
struct HeapStruct {
	int Capacity;
	int Size;
	ElementType* Elements;
};
//
PriorityQueue Initialize(int MaxElements) {
	PriorityQueue H;
	if (MaxElements < MinPQSize)
		printf("Priority queue size is too small");
	H = (HeapStruct*)malloc(sizeof(struct HeapStruct));
	if (H == NULL)
		printf("out of space!!!");
	/* Allocate the array plus on extra for sentinel */
	H->Elements = (ElementType*)malloc((MaxElements + 1) * sizeof(ElementType));
	if (H->Elements == NULL)
		printf("out of space!!!");
	H->Capacity = MaxElements;
	H->Size = 0;
	H->Elements[0] = MinData;
	return H;
}

//插入到一个二叉堆的过程
/* H->Element[0] is a sentinel */
void Insert(ElementType X, PriorityQueue H) {
	int i;
	if (IsFull(H)) {
		printf("Priority queue is full");
		return;
	}
	for (i = ++H->Size; H->Elements[i / 2] > X; i /= 2)
		H->Elements[i] = H->Elements[i / 2];
	H->Elements[i] = X;
}

//在二叉堆中执行DeleteMin的函数
ElementType DeleteMin(PriorityQueue H) {
	int i, Child;
	ElementType MinElement, LastElement;
	if (IsEmpty(H)) {
		printf("Priority queue is empty");
		return H->Elements[0];
	}
	MinElement = H->Elements[1];
	LastElement = H->Elements[H->Size--];
	for (i = 1; i * 2 <= H->Size; i = Child) {
		/* Find smaller child */
		Child = i * 2;
		if (Child != H->Size && H->Elements[Child + 1] < H->Elements[Child])
			Child++;
		/* Percolate one level */
		if (LastElement > H->Elements[Child])
			H->Elements[i] = H->Elements[Child];
		else
			break;
	}
	H->Elements[i] = LastElement;
	return MinElement;
}

/*
//BuildHeap的简要代码
for (i = N / 2; i > 0; i--)
PercolateDown(i);
*/

6.2 左式堆

零路径

#include<stdio.h>
#include<stdlib.h>

typedef int ElementType;
//左式堆类型声明
#ifndef _LeftHeap_H

struct TreeNode;
typedef struct TreeNode* PriorityQueue;

/* Minimal set of priority queue operations */
/* Note that nodes will be shared among several */
/* leftist heaps after a merge; the user must */
/* make sure to not use the old leftist heaps */

PriorityQueue Initialize(void);
ElementType FindMin(PriorityQueue H);
int IsEmpty(PriorityQueue H);
PriorityQueue Merge(PriorityQueue H1, PriorityQueue H2);

#define Insert(X,H) (H=Insert1(X),h))
/* DeleteMin macro is left as an exercise */
PriorityQueue Insert1(ElementType X, PriorityQueue H);
PriorityQueue DeleteMin1(PriorityQueue H);

#endif

/* Place in implementation file */
struct TreeNode {
	ElementType Element;
	PriorityQueue Left;
	PriorityQueue Right;
	int Npl;
};
//
PriorityQueue Merge(PriorityQueue H1, PriorityQueue H2) {
	if (H1 == NULL)
		return H2;
	if (H2 == NULL)
		return H1;
	if (H1->Element < H2->Element)
		return Merge1(H1, H2);
	else
		return Merge1(H2, H1);
}
static PriorityQueue Merge1(PriorityQueue H1, PriorityQueue H2) {
	if (H1->Left == NULL)/* Single node */
		H1->Left = H2;/* H1->Right is already 0*/
	else {
		H1->Right = Merge(H1->Right, H2);
		if (H1->Left->Npl < H1->Right->Npl)
			SwapChildren(H1);
		H1->Npl = H1->Right->Npl + 1;
	}
	return H1;
}
PriorityQueue Insert1(ElementType X, PriorityQueue H) {
	PriorityQueue SingleNode;
	SingleNode = (PriorityQueue)malloc(sizeof(struct TreeNode));
	if (SingleNode == NULL)
		printf("out of space");
	else {
		SingleNode->Element = X;
		SingleNode->Npl = 0;
		SingleNode->Left = SingleNode->Right = NULL;
		H = Merge(SingleNode, H);
	}
	return H;
}
/* DeleteMin1 returns the new tree; */
/* To get the minimum,use FindMin */
/* This is for convenience */
PriorityQueue DeleteMin1(PriorityQueue H) {
	PriorityQueue LeftHeap, RightHeap;
	if (IsEmpty(H)) {
		printf("Priority queue is empty");
		return H;
	}
	LeftHeap = H->Left;
	RightHeap = H->Right;
	free(H);
	return Merge(LeftHeap, RightHeap);
}

6.3 二项队列结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1Kndj7sJ-1675990011913)(D:/pictures/6.png)]

#include<stdio.h>
#include<stdlib.h>

typedef int ElementType;
#define MaxTrees 99
#define Infinity 99999
//二项队列类型声明
typedef struct BinNode* BinTree;
typedef struct BinNode* Position;
typedef struct Collection* BinQueue;

struct BinNode {
	ElementType Element;
	Position LeftChild;
	Position NextSibling;
};
struct Collection {
	int CurrentSize;
	BinTree TheTrees[MaxTrees];
};
//合并同样大小两棵二项树的例程
/* Return the result of merging equal-sized T1 and T2 */
BinTree CombineTrees(BinTree T1, BinTree T2) {
	if (T1->Element > T2->Element)
		return CombineTrees(T2, T1);
	T2->NextSibling = T1->LeftChild;
	T1->LeftChild = T2;
	return T1;
}
BinTree combinTrees(BinTree T1, BinTree T2) {
	if (T1->Element > T2->Element)
		return combinTrees(T2, T1);
	T2->NextSibling = T1->LeftChild;
	T1->LeftChild = T2;
	return T1;
}
//合并两个优先队列的例程
/* Merge two binomial queues */
/* Not optimized for early termination */
/* H1 contains merged result */
BinQueue Merge(BinQueue H1, BinQueue H2) {
	BinTree T1, T2, Carry = NULL;
	int i, j;
	if (H1->CurrentSize + H2->CurrentSize > Capacity)
		printf("Merge would exceed capacity");
	H1->CurrentSize += H2->CurrentSize;
	for (i = 0, j = 1; j <= H1->CurrentSize; i++, j *= 2) {
		T1 = H1->TheTrees[i];
		T2 = H2->TheTrees[i];
		switch (!!T1 + 2 * !!T2 + 4 * !!Carry) {/* 0 1  */
		case 0:/* No trees */
		case 1:/* Only H1 */
			break;
		case 2:/* Only H2 */
			H1->TheTrees[i] = T2;
			H2->TheTrees[i] = NULL;
			break;
		case 4:/* Only Carry */
			H1->TheTrees[i] = Carry;
			Carry = NULL;
			break;
		case 3:/* H1 and H2 */
			Carry = CombineTrees(T1, T2);
			H1->TheTrees[i] = H2->TheTrees[i] = NULL;
			break;
		case 5:/* H1 and Carry */
			Carry = CombineTrees(T1, Carry);
			H1->TheTrees[i] = NULL;
			break;
		case 6:/* H2 and Carry */
			Carry = CombineTrees(T2, Carry);
			H2->TheTrees[i] = NULL;
			break;
		case 7:/* All three */
			H1->TheTrees[i] = Carry;
			Carry = CombineTrees(T1, T2);
			H2->TheTrees[i] = NULL;
			break;
		}
	}
	return H1;
}
//二项队列的DeleteMin
ElementType DeleteMin(BinQueue H) {
	int i, j;
	int MinTree;/* The tree with the minimum item */
	BinQueue DeletedQueue;
	Position DeletedTree, OldRoot;
	ElementType MinItem;
	if (IsEmpty(H)) {
		printf("Empty binomial queue");
		return -Infinity;
	}
	MinItem = Infinity;
	for (i = 0; i < MaxTrees; i++) {
		if (H->TheTrees[i] && H->TheTrees[i]->Element < MinItem) {
			/* Update minimum */
			MinItem = H->TheTrees[i]->Element;
			MinTree = i;
		}
	}
	DeletedTree = H->TheTrees[MinTree];
	OldRoot = DeletedTree;
	DeletedTree = DeletedTree->LeftChild;
	free(OldRoot);
	DeletedQueue = Initialize();
	DeletedQueue->CurrentSize = (1 << MinTree) - 1;
	for (j = MinTree - 1; j >= 0; j--) {
		DeletedQueue->TheTrees[j] = DeletedTree;
		DeletedTree = DeletedTree->NextSibling;
		DeletedQueue->TheTrees[j]->NextSibling = NULL;
	}
	H->TheTrees[MinTree] = NULL;
	H->CurrentSize -= DeletedQueue->CurrentSize + 1;
	Merge(H, DeletedQueue);
	return MinItem;
}

7 排序

整个排序工作能够在主存中完成,元素的个数相对来说比较小(小于10^6)。不能在主存中完成而必须在磁盘或磁带上完成的排序也相当重要。这种类型的排序叫做外部排序。

插入,冒泡,选择n^2

7.1 插入排序

typedef int ElementType;
//插入排序例程
void InsertSort(ElementType A[], int N) {
	int j, P;
	ElementType Tmp;
	for (P = 1; P < N; P++) {
		Tmp = A[P];
		for (j = P; j > 0 && A[j - 1] > Tmp; j--)
			A[j] = A[j - 1];
		A[j] = Tmp;
	}
}

7.2 希尔排序

(缩小增量排序)

typedef int ElementType;
//使用希尔增量的希尔排序例程(可能有更好的增量)
void Shellsort(ElementType A[], int N) {
	int i, j, Increment;
	ElementType Tmp;
	for (Increment = N / 2; Increment > 0; Increment /= 2) 
		for (i = Increment; i < N; i++) {
			Tmp = A[i];
			for (j = i; j >= Increment; j -= Increment)
				if (Tmp < A[j - Increment])
					A[j] = A[j - Increment];
				else
					break;
			A[j] = Tmp;
		}
}

7.3 堆排序

typedef int ElementType;
#define LeftChild(i)(2*(i)+1)
//堆排序
void PercDown(ElementType A[], int i, int N) {
	int Child;
	ElementType Tmp;
	for (Tmp = A[i]; LeftChild(i) < N; i = Child) {
		Child = LeftChild(i);
		if (Child != N - 1 && A[Child + 1] > A[Child])
			Child++;
		if (Tmp < A[Child])
			A[i] = A[Child];
		else
			break;
	}
	A[i] = Tmp;
}

void Swap(ElementType* a, ElementType* b) {
	ElementType Tmp = *a;
	*a = *b;
	*b = Tmp;
}

void Heapsort(ElementType A[], int N) {
	int i;
	for (i = N / 2; i >= 0; i--)/* BuildHeap */
		PercDown(A, i, N);
	for (i = N - 1; i > 0; i--) {
		Swap(&A[0], &A[i]);/* DeleteMax */
		PercDown(A, 0, i);
	}
}

7.4 归并排序

#define Error(Str) FatalError(Str)
#define FatalError(Str) fprintf(stderr, "%s\n", Str), exit(1)
typedef int ElementType;

//归并排序例程
void MSort(ElementType A[], ElementType TmpArray[], int Left, int Right) {
	int Center;
	if (Left < Right) {
		Center = (Left + Right) / 2;
		MSort(A, TmpArray, Left, Center);
		MSort(A, TmpArray, Center + 1, Right);
		Merge(A, TmpArray, Left, Center + 1, Right);
	}
}
void Mergesort(ElementType A[], int N) {
	ElementType* TmpArray;
	TmpArray = (ElementType*)malloc(N * sizeof(ElementType));
	if (TmpArray != NULL) {
		MSort(A, TmpArray, 0, N - 1);
		free(TmpArray);
	}
	else
		FatalError("No space for tmp array!!!");
}
/* Lpos = start of left half, Rpos = start of right half */
void Merge(ElementType A[], ElementType TmpArray[], int Lpos, int Rpos, int RightEnd) {
	int i, LeftEnd, NumElements, TmpPos;
	LeftEnd = Rpos - 1;
	TmpPos = Lpos;
	NumElements = RightEnd - Lpos + 1;
	/* main loop */
	while (Lpos <= LeftEnd && Rpos <= RightEnd)
		if (A[Lpos] <= A[Rpos])
			TmpArray[TmpPos++] = A[Rpos++];
	while (Lpos <= LeftEnd)/* Copy rest of first half */
		TmpArray[TmpPos++] = A[Rpos++];
	/* Copy TmpArray back */
	for (i = 0; i < NumElements; i++, RightEnd--)
		A[RightEnd] = TmpArray[RightEnd];
}

7.5 快速排序

D&C

n log n

#define Error(Str) FatalError(Str)
#define FatalError(Str) fprintf(stderr, "%s\n", Str), exit(1)
typedef int ElementType;

void Swap(ElementType* a, ElementType* b) {
	ElementType Tmp = *a;
	*a = *b;
	*b = Tmp;
}

//插入排序例程
void InsertionSort(ElementType A[], int N) {
	int j, P;
	ElementType Tmp;
	for (P = 1; P < N; P++) {
		Tmp = A[P];
		for (j = P; j > 0 && A[j - 1] > Tmp; j--)
			A[j] = A[j - 1];
		A[j] = Tmp;
	}
}
//快速排序的驱动程序
void Quicksort(ElementType A[], int N) {
	Qsort(A, 0, N - 1);
}

//实现三数中值分割方法的程序
/* Return median of Left, Center, and Right */
/* Order these and hide the pivot */
ElementType Median3(ElementType A[], int Left, int Right) {
	int Center = (Left + Right) / 2;
	if (A[Left] > A[Center])
		Swap(&A[Left], &A[Center]);
	if (A[Left] > A[Right])
		Swap(&A[Left], &A[Right]);
	if (A[Center] > A[Right])
		Swap(&A[Center], &A[Right]);
	/* Invariant:A[Left]<=A[Center]<=A[Right] */
	Swap(&A[Center], &A[Right - 1]);/* Hide pivot */
	return A[Right - 1];/* return pivot */
}
//快速排序的主例程
#define Cutoff (3)
void Qsort(ElementType A[], int Left, int Right) {
	int i, j;
	ElementType Pivot;
	if (Left + Cutoff <= Right) {
		Pivot = Median3(A, Left, Right);
		i = Left;
		j = Right - 1;
		for (;;) {
			while (A[++i] < Pivot) {}
			while (A[--j] > Pivot) {}
			if (i < j)
				Swap(&A[i], &A[j]);
			else
				break;
		}
		Swap(&A[i], &A[Right - 1]);/* Restore pivot */
		Qsort(A, Left, i - 1);
		Qsort(A, i + 1, Right);
	}
	else/* Do an insertion sort on the subarray */
		InsertionSort(A + Left, Right - Left + 1);
}
//快速选择的主例程
/* Places the kth smallest element in the kth position */
/* Because arrays start at 0, this will be index k-1 */
void Qselect(ElementType A[], int k, int Left, int Right) {
	int i, j;
	ElementType Pivot;
	if (Left + Cutoff <= Right) {
		Pivot = Median3(A, Left, Right);
		/*
		i = Left;
		j = Right - 1;
		for (;;) {
			while (A[++i] < Pivot) {}
			while (A[--j] > Pivot) {}
			if (i < j)
				Swap(&A[i], &A[j]);
			else
				break;
		}
		*/
		i = Left + 1; j = Right - 2;
		for (;;) {
			while (A[i] < Pivot)i++;
			while (A[j > Pivot])j--;
			if (i < j)Swap(&A[i], &A[j]);
			else break;
		}
		Swap(&A[i], &A[Right - 1]);/* Restore pivot */
		if (k <= i)
			Qselect(A, k, Left, i - 1);
		else if (k > i + 1)
			Qselect(A, k, i + 1, Right);
	}
	else/* Do an insertion sort on the subarray */
		InsertionSort(A + Left, Right - Left + 1);
}
typedef int ElementType;
void qsor(ElementType a[], int begin, int end) {
	if (begin > end)return;
	ElementType tem = a[begin];
	int i = begin;
	int j = end;
	while (i != j) {
		while (a[j] >= tem && j > i)j--;
		while (a[i] <= tem && j > i)i++;
		if (j > i) {
			ElementType t;
			t = a[i];
			a[i] = a[j];
			a[j] = t;
		}
	}
	a[begin] = a[i];
	a[i] = tem;
	qsorT(a, begin, i - 1);
	qsorT(a, i + 1, end);
}

7.6 桶式排序

7.7 外部排序

8 不相交集ADT

#include<stdio.h>
#include<stdlib.h>
#define NumSets 99
#define Error(Str) FatalError(Str)
#define FatalError(Str) fprintf(stderr, "%s\n", Str), exit(1)
typedef int ElementType;
//不相交集合的类型声明
#ifndef _DisjSet_H
typedef int DisjSet[NumSets + 1];
typedef int SetType;
typedef int ElementType;
void Initilialize(DisjSet S);
void SetUnion(DisjSet S, SetType Root1, SetType Root2);
SetType Find(ElementType X, DisjSet S);
#endif /* _DisjSet_H */
//不相交集合的初始化例程
void Initialize(DisjSet S) {
	int i;
	for (i = NumSets; i > 0; i--)
		S[i] = 0;
}
//Union(不是最好的方法)
/* Assumes Root1 and Root2 are roots */
/* union is a C keyword, so this routine */
/* is named SetUnion */
void SetUnionN(DisjSet S, SetType Root1, SetType Root2) {
	S[Root2] = Root1;
}
//一个简单不相交集合Find算法
SetType FindS(ElementType X, DisjSet S) {
	if (S[X] <= 0)
		return X;
	else
		return FindS(S[X], S);
}
//按高度(秩)求并的程序
/* Assumes Root1 and Root2 are roots */
/* union is a C keyword, so this routine */
/* is named SetUnion */
void SetUnion(DisjSet S, SetType Root1, SetType Root2) {
	if (S[Root2] < S[Root1])/* Root2 is deeper set */
		S[Root1]=Root2;/* Make Root2 new root */
	else {
		if (S[Root1] == S[Root2])/* Same height */
			S[Root1]--;/* suo update */
		S[Root2] = Root1;
	}
}
//用路径压缩进行不相交集Find的程序
SetType Find(ElementType X, DisjSet S) {
	if (S[X] <= 0)
		return X;
	else
		return S[X] = Find(S[X], S);
}

9 图论算法

当前,还不存在找出从s到一个顶点的路径比找出从s到所有顶点路径更快(快多于一个常数因子)的算法。

9.6深度优先搜索的应用

双连通

如果一个连通的无向图中的任一顶点删除之后,剩下的图仍然连通,那么这样的无向连通图就是双连通的。

9.6.3欧拉回路

所有顶点的度(边的条数)均为偶数的任何连通图必然有欧拉回路。可以以线性时间找出这样一条回路。

9.6.5查找强分支

通过执行两次深度优先搜索,可以检测一个有向图是否是强连通的,如果它不是强连通的,那么我们实际上可以得到顶点的一些子集。

NP中的每一个问题都可以用一台非确定型计算机在多项式时间内求解。

除可满足问题外,哈米尔顿回路问题,巡回售货员问题,最长路径问题、图的着色问题以及团的问题都是著名的NP-完全问题。NP-完全问题相当广泛,包括来自操作系统(调度和安全)、数据库系统、运筹学、逻辑学、特别是图论等不同领域的问题。

10 算法设计技巧

10.1贪婪算法

如果所有的字符都以相同的频率出现,那么要节省空间是不可能的。

满树:所有的节点或者是树叶,或者有两个儿子。

近似装箱问题

存在使得任意联机装箱算法至少使用4/3最优箱子数的输入。

首次适合算法用到的大约比最优装箱方法多2%的箱子。

传统上,在正文中至少含有两个递归调用的例程叫做分治算法,而正文中只含一个递归调用的例程不是分治算法。

使用“五分化中项的中项”的快速选择算法的运行时间为O(N)。

10.3 动态规划

任何数学递归公式都可以直接翻译成递归算法。将递归算法重新写成非递归算法,让后者把那些子问题的答案系统地记录在一个表内。

在一步内删除一大组可能性的做法叫做裁剪。

12 高级数据结构及其实现

12.1 自顶向下伸展树

插入,查找(没找到最后一个节点展开)。

#include<stdio.h>
#include<stdlib.h>
#define Error(Str) FatalError(Str)
#define FatalError(Str) fprintf(stderr, "%s\n", Str), exit(1)
//伸展树:声明和初始化
typedef int ElementType;
#ifndef _Splay_H

struct SplayNode;
typedef struct SplayNode* SplayTree;
SplayTree MakeEmpty(SplayTree T);
SplayTree Find(ElementType X, SplayTree T);
SplayTree FinMin(SplayTree T);
SplayTree FindMax(SplayTree T);
SplayTree Initialize(void);
SplayTree Insert(ElementType X, SplayTree T);
SplayTree Remove(ElementType X, SplayTree T);
ElementType Retrieve(SplayTree T);/* Gets root item */
static Position SingleRotateWithLeft(Position k2);
static Position SingleRotateWithRight(Position k2);

#endif /* _Splay_H */
/* Place in the implementation file */
struct SplayNode {
	ElementType Element;
	SplayTree Left;
	SplayTree Right;
};
typedef struct SplayNode* Position;
static Position NullNode = NULL;/* Needs initialization */
static Position SingleRotateWithLeft(Position k2) {
	Position k1;
	k1 = k2->Left;
	k2->Left = k1->Right;
	k1->Right = k2;
	return k1;  /* New root */
}
static Position SingleRotateWithRight(Position k2) {
	Position k1;
	k1 = k2->Right;
	k2->Right = k1->Left;
	k1->Left = k2;
	return k1;  /* New root */
}
SplayTree Initialize(void) {
	if (NullNode == NULL) {
		NullNode = (Position)malloc(sizeof(struct SplayNode));
		if (NullNode == NULL)
			FatalError("out of space!!!");
		NullNode->Left = NullNode->Right = NULL;
	}
	return NullNode;
}
/* 自顶向下的展开过程 */
/* Top-down splay procedure, not requiring Item to be in the tree */
SplayTree Splay(ElementType Item, Position X) {
	static struct SplayNode Header;
	Position LeftTreeMax, RightTreeMin;
	Header.Left = Header.Right = NullNode;
	LeftTreeMax = RightTreeMin = &Header;
	NullNode->Element = Item;
	while (Item != X->Element) {
		if (Item < X->Element) {
			if (Item < X->Left->Element)
				X = SingleRotateWithLeft(X);
			if (X->Left == NullNode)
				break;
			/* Link right */
			RightTreeMin->Left = X;
			RightTreeMin = X;
			X = X->Left;
		}
		else {
			if (Item > X->Right->Element)
				X = SingleRotateWithRight(X);
			if (X->Right == NullNode)
				break;
			/* Link Left */
			LeftTreeMax->Right = X;
			LeftTreeMax = X;
			X = X->Right;
		}
	}/* while Item!=X->Element */
	/* Reassemble */
	LeftTreeMax->Right = X->Left;
	RightTreeMin->Left = X->Right;
	X->Left = Header.Right;
	X->Right = Header.Left;
	return X;
}
/* 自顶向下伸展树的插入 */
SplayTree Insert(ElementType Item, SplayTree T) {
	static Position NewNode = NULL;
	if (NewNode == NULL) {
		NewNode = (Position)malloc(sizeof(struct SplayNode));
		if (NewNode == NULL)
			FatalError("out of space!!!");
	}
	NewNode->Element = Item;
	if (T == NullNode) {
		NewNode->Left = NewNode->Right = NullNode;
		T = NewNode;
	}
	else {
		T = Splay(Item, T);
		if (Item < T->Element) {
			NewNode->Left = T->Left;
			NewNode->Right = T;
			T->Left = NullNode;
			T = NewNode;
		}
		else if (T->Element < Item) {
			NewNode->Right = T->Right;
			NewNode->Left = T;
			T->Right = NullNode;
		}
		else
			return T;/* Already in the tree */
	}
	NewNode = NULL;/* So next insert will call mmalloc */
	return T;
}
/* 自顶向下的删除过程 */
SplayTree Remove(ElementType Item, SplayTree T) {
	Position NewTree;
	if (T != NullNode) {
		T = Splay(Item, T);
		if (Item == T->Element) {
			/* Found it! */
			if (T->Left == NullNode)
				NewTree = T->Right;
			else {
				NewTree = T->Left;
				NewTree = Splay(Item, NewTree);
				NewTree->Right = T->Right;
			}
			free(T);
			T = NewTree;
		}
	}
	return T;
}


12.2红黑树

//使用两个标记对树的中序遍历
/* Print the tree,watch out for NullNode */
/* and skip header */
static void DoPrint(RedBlackTree T) {
	if (T != NullNode) {
		DoPrint(T->Left);
		Output(T->Element);
		DoPrint(T->Right);
	}
}
void PrintTree(RedBlackTree T) {
	DoPrint(T->Right);
}
#define FatalError(Str) fprintf(stderr, "%s\n", Str), exit(1)
typedef int ElementType;

//类型声明和初始化
struct RedBlackNode;
typedef enum ColorType{Red,Black}ColorType;
typedef RedBlackNode* RedBlackTree;
typedef RedBlackNode* Position;

struct RedBlackNode {
	ElementType Element;
	RedBlackTree Left;
	RedBlackTree Right;
	ColorType Color;
};
Position NullNode = NULL; /* Needs initialization */
/* Initialization procedure */
RedBlackTree Initialize(void) {
	RedBlackTree T;
	if (NullNode == NULL) {
		NullNode = (Position)malloc(sizeof(struct RedBlackNode));
		if (NullNode == NULL)
			FatalError("out of space");
		NullNode->Left = NullNode->Right = NullNode;
		NullNode->Color = Black;
		NullNode->Element = INFINITY;
		
	}
	/* Create the header node */
	T = (RedBlackTree)malloc(sizeof(struct RedBlackNode));
	if (T == NULL)
		FatalError("out of space");
	T->Element = -INFINITY;
	
	T->Left = T->Right = NullNode;
	T->Color = Black;
	return T;
}
/* 旋转过程 */
/* Perform a rotation at node X */
/* (whose parent is passed as a parameter) */
/* The child is deduced by examining Item */
static Position Rotate(ElementType Item, Position Parent) {
	if (Item < Parent->Element)
		return Parent->Left = Item < Parent->Left->Element ?
		SingleRotateWithLeft(Parent->Left) :
		SingleRotateWithRight(Parent->Left);
	else
		return Parent->Right = Item < Parent->Right->Element ?
		SingleRotateWithLeft(Parent->Right) :
		SingleRotateWithRight(Parent->Right);
}
/* 插入过程 */
static Position X, P, GP, GGP;
static void HandleReorient(ElementType Item, RedBlackTree T) {
	X->Color = Red;/* Do the color flip */
	X->Left->Color = Black;
	X->Right->Color = Black;
	if (P->Color == Red) /* Have to rotate */
    {
		GP->Color = Red;
		if ((Item < GP->Element) != (Item < P->Element))
			P = Rotate(Item, GGP);/* Start double rotation */
		X = Rotate(Item, GGP);
		X->Color = Black;
	}
	T->Right->Color = Black;/* Make root black */
}
RedBlackTree Insert(ElementType Item, RedBlackTree T) {
	X = P = GP = T;
	NullNode->Element = Item;
	while (X->Element != Item)/* Descend down the tree */
	{
		GGP = GP;
		GP = P;
		P = X;
		if (Item < X->Element)
			X = X->Left;
		else
			X = X->Right;
		if (X->Left->Color == Red && X->Right->Color == Red)
			HandleReorient(Item, T);
	}
	if (X != NullNode)
		return NullNode;/* Duplicate */
	X = (Position)malloc(sizeof(struct RedBlackNode));
	if (X == NULL)
		FatalError("out of space");
	X->Element = Item;
	X->Left = X->Right = NullNode;
	if (Item < P->Element)/* Attach to its parent */
		P->Left = X;
	else
		P->Right = X;
	HandleReorient(Item, T);/* Color red;maybe rotate */
	return T;	
}

//使用两个标记对树的中序遍历
/* Print the tree,watch out for NullNode */
/* and skip header */
static void DoPrint(RedBlackTree T) {
	if (T != NullNode) {
		DoPrint(T->Left);
		Output(T->Element);
		DoPrint(T->Right);
	}
}
void PrintTree(RedBlackTree T) {
	DoPrint(T->Right);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值