《数据结构与算法分析–C语言描述 2ed》第3章表、栈和队列 及 书本例子代码

3.2单链表

fatal.h

//fatal.h

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

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

list.h


		typedef int ElementType; //数据部分的数据类型
/* P39 START:figure 3-6 */
		#ifndef __LIST_H__
		#define __LIST_H__

		struct Node;

		typedef struct Node *PtrNode; //结点类型的指针
		typedef PtrNode List;         //头结点
		typedef PtrNode Position;     //中间某一节点

		List MakeEmpty(List L);                         //把链表全部结点置空
		int IsEmpty(List L);                            //判断链表是否是空表
		int IsLast(Position P, List L);                 //判断P是否是最后一个结点
		Position Find(ElementType X, List L);           //返回关键字首次出现的位置
		void Delete(ElementType X, List L);             //从链表中删除某一元素
		Position FindPrevious(ElementType X, List L);   //返回关键字的上一个位置
		void Insert(ElementType X, List L, Position P); //在某个位置,插入某个关键字
		void DeleteList(List L);
		Position Header(List L); //返回头结点
		Position First(List L);  //
		Position Advance(Position P);
		ElementType Retrieve(Position P);

		#endif
/* END */

list.c

		#include <stdlib.h>
		#include "list.h"
		#include "fatal.h"

		//节点的数据结构
		struct Node
		{
			ElementType Element;
			Position Next;
		};

		//清空链表,保留头结点
		List MakeEmpty(List L)
		{
			if (L != NULL)
				DeleteList(L);
			L = malloc(sizeof(struct Node));//??????????????
			if (L == NULL)
				FatalError("Out of memory! ");
			L->Next = NULL;
			return L;
		}

		//图3-8 判断链表是否是空表
		int IsEmpty(List L)
		{
			return (L->Next == NULL);
		}

		//图3-9 若P是L的最后一个节点返回true
		//参数L在实现中没有用到
		int IsLast(Position P, List L)
		{
			return (P->Next == NULL);
		}

		//图3-10 返回关键字首次出现的位置 
		// 成功:X的位置,失败:NULL
		Position Find(ElementType X, List L)
		{
			Position P;
			P = L->Next;
			while (P != NULL && P->Element != X)
			{
				P = P->Next;
			}
			return P;
		}

		//图3-11 删除链表L中第一次出现的X,
		//如果不存在就什么也不做(假设X存在于L)
		void Delete(ElementType X, List L)
		{
			Position P, TmpCell;
			P = FindPrevious(X, L);
			if (!IsLast(P, L))
			{
				TmpCell = P->Next;//此时TmpCell为待删除的节点
				P->Next = TmpCell->Next;//
				free(TmpCell);
			}
		}

		//图3-12 返回关键字的上一个位置
		//成功:X的上一个位置,失败:NULL
		//提供给Delete使用
		Position FindPrevious(ElementType X, List L)
		{
			Position P;
			P = L;
			while (P->Next != NULL && P->Next->Element != X)
			{
				P = P->Next;
			}
			return P;
		}

		//figure3-13 在某个位置,插入某个关键字
		void Insert(ElementType X, List L, Position P)
		{
			if (P == NULL)
			{
				return;
			}
			Position TmpCell;
			TmpCell = malloc(sizeof(struct Node));
			if (TmpCell == NULL)
			{
				FatalError("malloc space error!");
			}
			TmpCell->Element = X;
			TmpCell->Next = P->Next;
			P->Next = TmpCell;
		}

		//figure3-15 删除整张表
		void DeleteList(List L)
		{
			Position P, TmpCell;
			P = L->Next;
			L->Next = NULL;
			while (P != NULL)
			{
				TmpCell = P->Next;
				free(P);
				P = TmpCell;
			}
		}
		Position Header(List L)//返回头结点
		{
			return L;
		}
		Position First(List L)//
		{
			return L->Next;
		}
		Position Advance(Position P)
		{
			return P->Next;
		}
		ElementType Retrieve(Position P)
		{
			return P->Element;
		}

testlist.c

#include <stdio.h>
#include "list.h"

void PrintList(const List L)
{
	Position P = Header(L);
	if (IsEmpty(L))
		printf("Empty List\n");
	else
	{
		do
		{
			P = Advance(P);
			printf("%d ", Retrieve(P));
		} while (!IsLast(P, L));
		printf("\n");
	}
}
int main()
{
	List L = NULL;
	Position P = NULL;
	int i=0;

	L = MakeEmpty(L);
	P = Header(L);
	PrintList(L);

	for (i = 0; i < 10; i++)
	{
		Insert(i, L, P);
		PrintList(L);
		P = Advance(P);
	}
	for (i = 0; i < 10; i += 2)
	{
		Delete(i, L);//删除偶数
	}
	for (i = 0; i < 10; i++)
	{
		if ((i % 2 == 0) == (Find(i, L) != NULL))
		{//若是find到偶数,说明删除错误
			printf("Find fails\n");
		}
	}

	printf("Finish deletions\n");
	PrintList(L);
	DeleteList(L);

	system("pause");

	return 0;
}

3.3栈-链表实现

fatal.h

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

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

stacklist.h


		typedef int ElementType;
/* START figure 3-39 */
		#ifndef __STACKLIST_H__
		#define __STACKLIST_H__

		struct Node;
		typedef struct Node *PtrToNode;
		typedef PtrToNode Stack;

		int IsEmpty(Stack S); //figure 3-40 测试栈是否是空栈

		Stack CreateStack(void); //创建一个空栈,置空,头指针的Next指向NULL
		void MakeEmpty(Stack S);	//
		void DisposeStack(Stack S); //彻底销毁栈,包括头指针
		void Push(ElementType X, Stack S); //入栈--向栈顶(链表前端)进行插入
		ElementType Top(Stack S); //查看栈的第一个元素
		void Pop(Stack S); //删除栈顶元素

		#endif // !__STACK_H__
/* END */

stacklist.c

		#include <stdlib.h>
		#include "stacklist.h"
		#include "fatal.h"

		struct Node
		{
			ElementType Element;
			PtrToNode Next;
		};

		//figure 3-40 测试栈是否是空栈
		int IsEmpty(Stack S)
		{
			return (S->Next == NULL);
		}
		
		//figure3-41 创建一个空栈,头指针的Next指向NULL
		Stack CreateStack(void)
		{
			Stack S;
			S = malloc(sizeof(struct Node));
			if (S == NULL)
				FatalError("malloc error,Out of space");
			MakeEmpty(S);
			return S;
		}
		void MakeEmpty(Stack S)
		{
			if (S == NULL)
				FatalError("Must use CreateStack First");
			else
			{
				while (!IsEmpty(S))
				{
					Pop((S));
				}
			}
		}

		//彻底销毁栈,包括头指针
		void DisposeStack(Stack S)
		{
			MakeEmpty(S);
			free(S);
		}
		
		//figure3-42 入栈--向栈顶(链表前端)进行插入
		void Push(ElementType X, Stack S)
		{
			PtrToNode TmpCell;
			TmpCell = malloc(sizeof(struct Node));
			if (TmpCell == NULL)
				FatalError("Malloc Error!");
			else
			{
				TmpCell->Element = X;
				TmpCell->Next = S->Next;
				S->Next = TmpCell;
			}
		}

		//figure 3-43
		ElementType Top(Stack S)//查看栈的第一个元素
		{
			if (!IsEmpty(S))
			{
				return S->Next->Element;
			}
			FatalError("Empty Stack");
			return 0;
		}
		//figure 3-44
		void Pop(Stack S)//删除栈顶元素
		{
			PtrToNode FirstCell;
			if (IsEmpty(S))
				FatalError("Empty Stack");
			else
			{
				FirstCell = S->Next;
				if ( (S->Next != NULL) && (S->Next->Next != NULL) )
				{
					S->Next = S->Next->Next;
					free(FirstCell);
				}
				else 
				{
					S->Next = NULL;
					free(FirstCell);
				}
				
			}
		}

test_stack_list.c

#include <stdio.h>
#include "stacklist.h"

int main()
{
	Stack S = NULL;
	int i = 0;

	S = CreateStack();
	for (i = 0; i < 10; i++)
	{
		Push(i, S);
	}

	while (!IsEmpty(S))
	{
		printf("%d\n", Top(S));
		Pop(S);
	}

	DisposeStack(S);

	system("pause");
	return 0;
}

3.3栈-数组实现

fatal.h

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

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

stackArray.h

		typedef int ElementType;
/* START figure 3-45 */
		#ifndef __STACKARRAY_H__
		#define __STACKARRAY_H__

		struct StackRecord;
		typedef struct StackRecord * Stack;	//定义指针变量

		int IsEmpty(Stack S);				//栈是否是空栈
		int IsFull(Stack S);				//栈是否满
		Stack CreateStack(int MaxElements);	//创建指定容量的栈
		void DisposeStack(Stack S);			//释放栈
		void MakeEmpty(Stack S);			//使栈为空
		void Push(ElementType X, Stack S);	//入栈
		ElementType Top(Stack S);			//查看栈顶元素
		void Pop(Stack S);					//出栈
		ElementType TopAndPop(Stack S);		//查看栈顶元素并出栈

		#endif // !__STACKARRAY_H__
/* END */

stackArray.c

		#include <stdlib.h>
		#include "stackArray.h"
		#include "fatal.h"

		#define EmptyTOS (-1)
		#define MinStackSize (5)
		struct StackRecord
		{
			int Capacity;		//容量(数组元素个数)
			int TopOfStack;		//栈顶(元素在数组中的下标)
			ElementType *Array;	//数组的首地址
		};

		//figure3-48 栈是否是空栈
		int IsEmpty(Stack S)				
		{
			return (S->TopOfStack == EmptyTOS);
		}
		//栈是否满
		int IsFull(Stack S)
		{
			return (S->TopOfStack == (S->Capacity - 1));
		}
		//figure3-46创建指定容量的栈
		Stack CreateStack(int MaxElements)
		{
			Stack S;
			if (MaxElements < MinStackSize)
				FatalError("Stack size is too small");
			S = malloc(sizeof(struct StackRecord));
			if (S == NULL)
				FatalError("malloc()error,Out of space");
			S->Array = malloc(sizeof(ElementType)*MaxElements);
			if (S->Array == NULL)
				FatalError("malloc()error,Out of space");
			S->Capacity = MaxElements;
			MakeEmpty(S);
			return S;
		}
		//figure3-47 释放栈
		void DisposeStack(Stack S)
		{
			if (S != NULL)
			{
				free(S->Array);
				free(S);
			}
		}
		//3-49使栈为空
		void MakeEmpty(Stack S)
		{
			S->TopOfStack = EmptyTOS;
		}
		//3-50入栈
		void Push(ElementType X, Stack S)
		{
			if (!IsFull(S))
				S->Array[++S->TopOfStack] = X;
			else
				FatalError("Empty Stack");

		}
		//figure3-51 查看栈顶元素
		ElementType Top(Stack S)
		{
			if (!IsEmpty(S))
				return (S->Array[S->TopOfStack]);
			FatalError("Empty Stack");
			return 0;
		}
		//figure3-52 出栈
		void Pop(Stack S)
		{
			if (!IsEmpty(S))
				S->TopOfStack--;
			else
				FatalError("Empty Stack");
		}
		//figure3-53 查看栈顶元素并出栈
		ElementType TopAndPop(Stack S)
		{
			if (!IsEmpty(S))
				return (S->Array[S->TopOfStack--]);
			FatalError("Empty Stack");
			return 0;
		}

test_stackArray.c

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

int main()
{
	Stack S = NULL;
	int i = 0;
	S = CreateStack(12);
	for (i = 0; i < 10; i++)
		Push(i, S);
	while (!IsEmpty(S))
	{
		printf("%d\n", Top(S));
		Pop(S);
	}
	DisposeStack(S);
	system("pause");
	return 0;
}

栈的应用实例

平衡符号

每一个右花括号、右方括号及右圆括号必然对应其相应的左括号,序列“{ [ ( ) ] }”是合法的
解法:
	这个简单的算法用到一个栈
	做一个空栈。读入字符直到文件尾。
	如果字符是一个开放符号,则将其推入栈中。
	如果字符是一个封闭符号,则当栈空时报错;否则,将栈元素弹出。
	如果弹出的符号不是对应的开放符号,则报错。在文件尾,如果栈非空则报错。

后缀表达式

后缀(postfix)或逆波兰(reverse Polish) 记法
例子:
	标准表达式:4.99*1.06+5.99+6.99*1.06=18.69
	后缀表达式:4.99 1.06 * 5.99 + 6.99 1.06 * +
解法:
	最容易的方法是使用一个栈。
	当见到一个数时就把它推入栈中;
	在遇到一个运算符时该运算符就作用于从该栈弹出的两个数(符号)上,将所得结果推入栈中。
处理时间:
	计算一个后缀表达式花费的时间是O(N),因为对输入中的每个元素的处理都是有一些栈操作组成,从而花费常数时间
注意:
	当一个表达式以后缀记号给出时,没有必要知道任何优先规则。这是一个明显的优点

后缀到中缀的转换

用栈将一个标准形式的表达式(或者叫中缀式(infix)转换成后缀式)
注意:假设这些操作符是从左到右结合的
例子:
	a+b*c+(d*e+f)*g
	a b c * + d e * f + g * +
	本例子中我们只使用+ * ( )
	优先级从高到低为:( * +
解法:
	基本原则:
		1.当读到一个数的时候,立即把它放到输出中。
		2.当读到一个操作符时,进栈而不是放到输出中,当遇到"("(右括号、开括号)时我们也要将其推入栈中。
		3.如果遇到一个右括号"(",就将栈元素弹出,直到遇到左括号")",但是左括号只被弹出,并不输出。
		## 标题4.如果遇到符号("+""*""("),我们就从栈中弹出直到发现优先级更低的元素为止(即:弹出优先级高的符号);
		  当从栈弹出元素的工作完成后,我们再将这个操作符压入栈中。
		5.有一个例外,除非是在处理一个")"的时候,否则绝对不从栈中移走"("6.最后,如果读到输入的末尾,我们将栈元素弹出直到该栈变成空栈,将符号写到输出中。
时间:只需要O(N)时间并经过一趟输入后运算即可完成
改进:可以通过指定减法和加法有相同的优先级以及乘法和除法有相同的优先级,而将减法和除法添加到指令集中
	 一种巧妙的想法是将表达式“a-b-c”转换成“a b - c -”而不是转换成“a b c - -

3.4队列

fatal.h

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

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

queue.h

		typedef int ElementType;
/* START figure 3-45 */
		#ifndef __QUEUE_H__
		#define __QUEUE_H__

		struct QueueRecord;
		typedef struct QueueRecord * Queue;	//定义指针变量

		int IsEmpty(Queue Q);				//队列是否是空队列
		int IsFull(Queue Q);				//队列是否满
		Queue CreateQueue(int MaxElements);	//创建指定容量的队列
		void DisposeQueue(Queue Q);			//释放队列
		void MakeEmpty(Queue Q);			//使队列为空
		static int Succ(int Value, Queue Q);//移动队头、队尾元素的位置,形成循环队列
		void Enqueue(ElementType X, Queue Q);//入队列-队尾
		ElementType Front(Queue Q);			//查看队列顶元素
		void Dequeue(Queue Q);				//出队列
		ElementType FrontAndDequeue(Queue Q);//查看队列顶元素并出队列

		#endif // !__Queue_H__
/* END */

queue.c

		#include <stdlib.h>
		#include "queue.h"
		#include "fatal.h"

#define MinQueueSize (5)

struct QueueRecord
{
	int Capacity;
	int Front;//队头元素在数组中的下标
	int Size;//队的实际元素个数
	int Rear;//队尾元素在数组中的下标
	ElementType * Array;
};

//figure 3-58 
int IsEmpty(Queue Q)
{
	return (Q->Size == 0);
}

int IsFull(Queue Q)
{
	return (Q->Size == Q->Capacity);
}

Queue CreateQueue(int MaxElements)
{
	Queue Q;
	if (MaxElements < MinQueueSize)
		FatalError("Queue size is too  small");
	Q = malloc(sizeof(struct QueueRecord));
	if (Q == NULL)
		FatalError("Out of space!!!");
	Q->Array = malloc(sizeof(struct QueueRecord)*MaxElements);
	if (Q->Array == NULL)
		FatalError("Out of space!!!");
	Q->Capacity = MaxElements;
	MakeEmpty(Q);
	return (Q);
}

//figure 3-59 构件空队列
void MakeEmpty(Queue Q)
{
	Q->Size = 0;
	Q->Front = 1;
	Q->Rear = 0;
}

void DisposeQueue(Queue Q)
{
	if (Q != NULL)
	{
		free(Q->Array);
		free(Q);
	}
}

//移动队头、队尾元素的位置,形成循环队列
//若是队尾元素到达数组底端,就把队尾元素的下标置为0-->数组首部
static int Succ(int Value, Queue Q)
{
	if (++Value == Q->Capacity)
		Value = 0;
	return Value;
}
//figure 3-60 入队
void Enqueue(ElementType X, Queue Q)
{
	if (IsFull(Q))
	{
		FatalError("Full Queue");
	}
	else
	{
		Q->Size++;
		Q->Rear = Succ(Q->Rear, Q);
		Q->Array[Q->Rear] = X;
	}
}

ElementType Front(Queue Q)
{
	if(!IsEmpty(Q))
		return (Q->Array[Q->Front]);
	FatalError("Empty Queue");
	return 0;
}

void Dequeue(Queue Q)
{
	if(IsEmpty(Q))
		FatalError("Empty Queue");
	else
	{
		Q->Size--;
		Q->Front = Succ(Q->Front, Q);
	}
}

ElementType FrontAndDequeue(Queue Q)
{
	ElementType X = 0;
	if(IsEmpty(Q))
		FatalError("Empty Queue");
	else
	{
		Q->Size--;
		X = Q->Array[Q->Front];
		Q->Front = Succ(Q->Front, Q);
	}
	return X;
}

test_queue.c

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

int main()
{
	Queue Q = CreateQueue(12);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		Enqueue(i, Q);
	}

	while (!IsEmpty(Q))
	{
		printf("%d\n", Front(Q));
		Dequeue(Q);
	}

	DisposeQueue(Q);

	system("pause");
	return 0;
}
发布了12 篇原创文章 · 获赞 10 · 访问量 7173

猜你喜欢

转载自blog.csdn.net/liangwenhao1108/article/details/104378944
今日推荐