单链表操作,队列,栈实现,以及常见字符串库函数经典实现

来源:互联网 发布:赛车网络手游 编辑:程序博客网 时间:2024/05/19 12:38

   马上快要找工作了,数据结构和算法,很多基础的东西久了没用已经很不熟练了,必须开始重拾了!,链表最简单,先从链表入手,后面再写系列的链表面试题总结以及其他数据结构,下面的代码参考了殷人昆老师的教材(数据结构c语言描述),程序在自己电脑的vc 6.0上能通过,可能有哪些地方不对的,或者有更精练的实现还指出来大家一起学习~


/************************************************************************//*                 (带头结点)单链表的结构及基本操作                                                1.迭代打印链表 2.尾递归打印链表 3.初始化链表 4.清空单链表 5.计算表的长度 6.判断链表是否为空 7.在链表中查找值为x的元素 8.在链表中查找第i个结点 9.将新元素x插入在链表第i个位置 10.删除第i个元素 11.将L2的链表复制到L1 12.前插法建链 13.尾插法建立链表*//************************************************************************/#include "stdafx.h"#include <stdlib.h>//链表的数据类型typedef int DataType;//链表的结构定义typedef struct node{DataType data;//数据域struct node *pNext;//指针域}LinkNode, *pNode;//检测内存分配错误void MemFail(pNode p){if (NULL == p){printf("内存分配出错!\n");exit(1);}}//1.迭代打印链表void PrintList(pNode pHead){pNode p = pHead->pNext;while (p != NULL){printf("%d ", p->data);p = p->pNext;}printf("\n");}//2.尾递归打印链表void PrintListRecursive(pNode pHead){if (pHead->pNext != NULL){printf("%d ", pHead->pNext->data);PrintListRecursive(pHead->pNext);}}//3.初始化链表void Initialize(pNode &pHead){pHead = new LinkNode();MemFail(pHead);pHead->pNext = NULL;//这一步容易忘记,链表最后一个结点指针域一定指向Null}//4.清空单链表void ClearList(pNode pHead){pNode p = NULL;while (pHead->pNext != NULL){p = pHead->pNext;pHead->pNext = p->pNext;delete p;p = NULL;}}//5.计算表的长度int GetLength(pNode pHead){int counter = 0;pNode p = pHead;while (p->pNext != NULL){p = p->pNext;counter++;}return counter;}//6.判断链表是否为空bool IsEmpty(pNode pHead){return (NULL == pHead->pNext);}//7.在链表中查找值为x的元素,没找到返回nullpNode FindData(pNode pHead, DataType x){pNode p = pHead->pNext;while (p != NULL && p->data != x){p = p->pNext;}return p;}//8.在链表中查找第i个结点,如果i不合法,函数返回nullpNode FindPos(pNode pHead, int i){if (i < 0){return NULL;}int counter = 0;pNode p = pHead;while (p != NULL && counter < i){counter++;p = p->pNext;}return p;}//9.将新元素x插入在链表第i个位置,若i不合理则返回false,否则返回truebool InsertEle(pNode pHead, DataType x, int i){pNode p = FindPos(pHead, i-1);if (NULL == p)//i不合法{return false;}//新增结点pNode pNew = new LinkNode();MemFail(pNew);pNew->data = x;//连接上新结点pNew->pNext = p->pNext;p->pNext = pNew;return true;}//10.删除第i个元素,若i不合理则返回false,删除的元素放到xbool DeleteEle(pNode pHead, int i, DataType &x){pNode p = FindPos(pHead, i - 1);if (NULL == p && NULL == p->pNext){return false;}//删除结点pNode pDel = p->pNext;x = pDel->data;p->pNext = pDel->pNext;delete pDel;pDel = NULL;}//11.将L2的链表复制到L1void Copy(pNode L1, pNode L2){if (NULL == L1){return;}pNode p2 = L2->pNext;pNode p1 = L1;while (p2 != NULL){pNode pNew = new LinkNode();MemFail(pNew);pNew->data = p2->data;p1->pNext = pNew;p1 = pNew;p2 = p2->pNext;}p1->pNext = NULL;//这一步易忘}//12.前插法建链 即新的元素总是插在头结点后面作为第一个结点//前插法的结果是数据的输入顺序与链表的顺序相反//下面这个函数将数组a的内容用前插法进行键链void InsertFront(pNode pHead, DataType a[], int n){if (NULL == pHead)//无效头结点{return;}for (int i=0; i<n; i++){//生成新结点pNode pNew = new LinkNode();MemFail(pNew);pNew->data = a[i];pNew->pNext = pHead->pNext;pHead->pNext = pNew;}}//13.尾插法建立链表 这个结果和上面的函数是相反的void insertTail(pNode pHead, DataType a[], int n){if (NULL == pHead)//头结点不合法{return;}pNode pTail = pHead;for (int i=0; i<n; i++){//生成新结点pNode pNew = new LinkNode();MemFail(pNew);pNew->data = a[i];pTail->pNext = pNew;pTail = pNew;}pTail->pNext = NULL;//链表收尾}


下面是基础的栈,和队列操作,vs2005上通过,虽然结构很简单,但亲自过手才是硬道理!


typedef int dataType;//栈数据类型#define MAX_SIZE 10//栈的最大容量//静态栈结构定义struct StaticStack{dataType elem[MAX_SIZE];//数据int top;//指向栈顶的指针};//栈的初始化void InitializeStaticStack(StaticStack &S){memset(S.elem, 0, sizeof(dataType) * MAX_SIZE);//top始终指向栈顶S.top = -1;}//将元素x压栈bool StaticStackPush(StaticStack &S, dataType x){//栈满if (MAX_SIZE - 1 == S.top){return false;}S.elem[++S.top] = x;return true;}//出栈bool StaticStackPop(StaticStack &S, dataType &x){//栈空if (-1 == S.top){return false;}x = S.elem[S.top--];return true;}/*void PrintStaticStack(StaticStack &S){for (int i=0; i<=S.top; i++){printf("%d ", S.elem[i]);}}*/#define INIT_SIZE 10//动态栈的初始大小#define INCREMENT 10//每次栈扩充的大小//动态栈结构定义struct DynamicStack{dataType *elem;//数据int top;//栈顶指针int maxSize;//栈的最大容量};//初始化动态栈void InitDynamicStack(DynamicStack &S){S.elem = (dataType *)calloc(INIT_SIZE, sizeof(dataType));if (NULL == S.elem){printf("Dynamic stack memory initialization error!");exit(1);}S.maxSize = INIT_SIZE;S.top = -1;}/*void PrintStaticStack(DynamicStack &S){for (int i=0; i<=S.top; i++){printf("%d ", S.elem[i]);}}*///压栈void DynamicStackPush(DynamicStack &DS, dataType x){//栈满,需要扩展if (DS.top == DS.maxSize - 1){DS.elem = (dataType *)realloc(DS.elem, DS.maxSize + INCREMENT);if (NULL == DS.elem){printf("Expand dynamic stack error!\n");exit(1);}}DS.elem[++DS.top] = x;DS.maxSize += INCREMENT;}//出栈bool DynamicStackPop(DynamicStack &DS, dataType &x){//栈空if (-1 == DS.top){return false;}x = DS.elem[DS.top--];return true;}#define QUEUE_SIZE 10//队列的大小//循环队列结构定义struct Queue{dataType elem[QUEUE_SIZE];//数据int front;//队首指针int rear;//队尾指针};//初始化队列void InitQueue(Queue &Q){memset(Q.elem, 0, sizeof(dataType) * QUEUE_SIZE);Q.front = 0;Q.rear = 0;}//入队bool EnQueue(Queue &Q, dataType x){//队列满if ((Q.rear + 1) % QUEUE_SIZE == Q.front){return false;}Q.elem[Q.rear] = x;Q.rear = (Q.rear + 1) % QUEUE_SIZE;return true;}//出队bool DeQueue(Queue &Q, dataType &x){//队列空if (Q.front == Q.rear){return false;}x = Q.elem[Q.front];Q.front = (Q.front + 1) % QUEUE_SIZE;return true;}//返回队列当前大小int GetQueueSize(Queue &Q){//注意别忘记加QUEUE_SIZE//当Q.rear - Q.front < 0时,需要加QUEUE_SIZE//当Q.rear - Q.front > 0时,如果加了QUEUE_SIZE后,需要对QUEUE_SIZE取模return (Q.rear - Q.front + QUEUE_SIZE) % QUEUE_SIZE;}/*void PrintQueue(Queue &Q){for (int i=Q.front; i!=Q.rear; i=(i+1)%QUEUE_SIZE){printf("%d ", Q.elem[i]);}printf("\n");}*/


最近把一些常见的c语言的字符串库函数参照着网上的程序自己实现了一下,也是方便自己复习总结,里面的实现比较经典,下面的函数在我电脑vs2005上都能通过,但未进行严格的测试。

/************************************************************************//* 1.strcpy函数实现   2.strncpy实现   3.strcat函数实现   4.strncat函数实现   5.strdup实现   6.strchr实现   7.strrchr函数实现   8.strpbrk函数   9.strstr实现   10.strlen实现   11.strlen另一种实现   12.strcmp函数实现   13.strcmpy的一种标准实现   14.strncpy函数实现   15.memset函数实现*/   /************************************************************************/


1.strcpy函数实现

//功能说明:将source的字符串复制到dest来//dest所指向的空间必须有足够的内存来容纳source所指向的字符串char * my_strcpy(char *dest, const char *source){assert(dest!=NULL && source!=NULL);char *r = dest;//*(dest++),先返回*dest, 然后dest++//(*(dest++) = *(source++)返回最左边表达式的值while ((*(dest++)=*(source++)) != '\0');return r;}/*1.注意参数的命名上规范,让人容易明白怎么使用函数2.第二个参数类型是const char *,防止修改源字符串3.函数返回值是char *,可以实现链式表达式4.参数合法性检查,下面的函数同样要遵循这些*/

2.strncpy实现

//将source的前n个字符串复制到destchar * my_strncpy(char *dest, const char *source, int n){assert(dest!=NULL && source!=NULL);char *r = dest;//注意n--和后面一堆不能换,否则会多复制一个while (n-- && (*(dest++)=*(source++))!='\0');return r;}

3.strcat函数实现

//将source指向的字符串链接在dest后面char * my_strcat(char *dest, const char *source){assert(dest!=NULL && source!=NULL);char *r = dest;while (*(dest) != '\0'){dest++;}while ((*(dest++)=*(source++)) != '\0');return r;}

 4.strncat函数实现

//将source特定数目字符串链接到dest后面char * my_strncat(char *dest, const char *source, int n){assert(dest!=NULL && source!=NULL);char *r = dest;while (*(dest) != '\0'){dest++;}while (n-- && (*(dest++)=*(source++))!='\0');return r;}

5.strdup实现

//该函数将预先配置内存,然后将制定字符串装入内存char * my_strdup(const char *pStr){assert(pStr != NULL);char *r = (char *)malloc(strlen(pStr)+1);if (NULL == r) {printf("Memory Failed!\n");exit(1);}return my_strcpy(r, pStr);}

6.strchr实现

//函数功能在字符串中查找指定的第一个字符,并返回指向该字符的指针//若未找到,则返回指向'\0'的字符串指针char * my_strchr(const char *pStr, char ch){assert(pStr != NULL);while (*pStr!='\0' && *pStr!=ch){pStr++;}return (char *)pStr;}

7.strrchr函数实现

//函数功能:查找一个字符c在另一个字符串str中末次出现的位置(也就是从str的右侧开始查找字符c首次出现的位置)char * my_strrchr(const char *pStr, char ch){assert(pStr != NULL);const char *r = NULL;while (*pStr != '\0'){if (*pStr == ch){r = pStr;}pStr++;}return (char *)r;}

8.strpbrk函数

//函数功能:在两个字符串中寻找首次共同出现的字符,返回该字符在str1中的地址char *my_strpbrk(const char *str1, const char *str2){assert(str1!=NULL && str2!=NULL);const char *tmp = str2;while (*str1 != '\0' ){tmp = str2;while (*tmp != '\0'){if (*str1 == *tmp){return (char *)str1; }tmp++;}str1++;}return NULL;}

9.strstr实现

//若字符串2包含在字符串1里面,返回它在字符串1中的位置,否则返回NULLchar * my_strstr(const char *strDes, const char *str){assert(strDes!=NULL && str!=NULL);const char *tmpDes = NULL;const char *tmpStr = NULL;while (*strDes != '\0'){for (tmpDes=strDes, tmpStr=str; *tmpDes==*tmpStr && *tmpStr!='\0';tmpDes++, tmpStr++){}if ('\0' == *tmpStr){return (char *)strDes;}strDes++;}return NULL;}

10.strlen实现

//该函数返回字符串长度,不包括后面的'\0'int my_strlen(const char *str){assert(str != NULL);int k = 0;while (++k && *(str++)!='\0');return k-1;}

11.strlen另一种实现

int my_strlen(const char *str){assert(str != NULL);const char *eos = str;//eos means end of stringwhile (*(eos++) != '\0');return (int)(eos - str - 1);}

12.strcmp函数实现

//两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇'\0'为止//s1>s2,返回值大于0,s1<s2返回值小于0,否则等于0int my_strcmp(const char *str1, const char *str2){assert(str1!=NULL && str2!=NULL); while (*str1!='\0' && *str2!='\0' && *str1==*str2){str1++;str2++;}return (*str1 - *str2);}

13.strcmpy的一种标准实现

int my_strcmp(const char *str1, const char *str2){assert(str1!=NULL && str2!=NULL); int ret = 0;while (!(ret=*(unsigned char *)str1-*(unsigned char *)str2) && *str2!='\0'){printf("%c - %c = %d\n", *str1, *str2, *str1-*str2);str1++;str2++;}if (ret > 0){return 1;}else if (ret < 0){return -1;}else{return 0;}}

14.strncpy函数实现

//函数比较两个字符串中前n个字符串大小int my_strncmp(const char *str1, const char *str2, int n){assert(str1!=NULL && str2!=NULL); if (n <= 0){return 0;}while (--n && *str1!='\0' && *str1==*str2){str1++;str2++;}return (*str1 - *str2);}

15.memset函数实现

//将指定内存区域的前count个字节设定为指定值void *my_memeset(void *buffer, int c, unsigned int count){if (count <= 0){return buffer;}assert(buffer != NULL);char *p = (char *)buffer;while (count--){*(p++) = (char)c;}return buffer;}


0 0
原创粉丝点击