- #pragma once 减少头文件组合,降低编译出错的概率
- 作用等效于
#ifndef FUNC_H
#define FUNC_H
代码主体
#endif
线性表的定义
- 排队问题
- 简单的线性表 (物理 或者逻辑结构)
- 1,数组
- 2,链表
- 线性表相关操作:
- 1,线性表初始化
- 2,线性表遍历
- 3,线性表插入元素
- 4,线性表删除元素
代码
#include <stdio.h>
#include <stdlib.h>
#define KSIZE 10
#define FALSE 0
#define TRUE 1
/************************************************************************/
/* 线性表(linear list)
线性表是一个相当灵活的数据结构,它的长度可以根据需要增长和缩短,即对线性表的数据元素不仅可以进行访问,还可以进行插入和删除等。
抽象定义的线性表如下:
ADT:Abstract Data Type 抽象数据类型
ADT LIST
L:LIST简称,即线性表本身
i:索引
e:element简称,即元素
cur_:current简称,即当前元素
pre_:previous简称,即前一个元素
next_:next,即下一个元素
visit:对元素访问的方式
InitList(&L) :初始化线性表
DestroyList(&L) :销毁线性表
ClearList(&L) :清空线性表
ListEmpty(L) :线性表是否为空
ListLength(L) :线性表中元素个数
GetElem(L, i, &e) :获取线性表中指定的元素
LocateElem(L, e, compare()) :给定元素获取第一次出现的索引位置
PriorElem(L, cur_ e, &pre_ e) :给定元素获取其前一个元素
NextElem(L, cur_ e, &next_ e) :给定元素获取其后一个元素
ListInsert(&L, i, e) :将元素插入链表中指定位置
ListDelete(&L, i, &e) :从链表中指定位置删除元素
ListTraverse(L, visit()) :遍历元素
简单线性表--C语言实现
线性表组成类型:int数组*/
/************************************************************************/
/*---------------------------------------
InitList(&L);
DestroyList(&L);
ClearList(&L);
ListEmpty(L);
ListLength(L);
GetElem(L, i, &e);
LocateElem(L, e, compare());
ListInsert(&L, i, e);
ListDelete(&L, i, &e);
ListTraverse(L, visit());
PriorElem(L, cur_ e, &pre_ e);
NextElem(L, cur_ e, &next_ e);
-----------------------------------------*/
int count;
void InitList(int *list);
void DestroyList(int *list);
void ClearList(int *list);
int ListEmpty(int *list);
int ListLength(int *list);
int GetElem(int *list, int i, int *e);
int LocateElem(int *list, int e);
int ListInsert(int *list, int i, int e);
int ListDelete(int *list, int i, int *e);
void ListTraverse(int *list);
int main(void)
{
int arr[KSIZE];
int e = 0;
InitList(arr);
ListInsert(arr, 0, 5);
ListInsert(arr, 0, 8);
ListInsert(arr, 1, 7);
ListTraverse(arr);
ListDelete(arr, 0, NULL);
ListTraverse(arr);
GetElem(arr, 1, &e);
printf("e = %d\n", e);
printf("5的索引是%d\n", LocateElem(arr, 5));
ClearList(arr);
if(ListEmpty(arr))
{
printf("线性表为空\n");
}
else
{
printf("线性表不为空\n");
}
printf("线性表的长度为%d\n", ListLength(arr));
DestroyList(arr);
system("pause");
return 0;
}
void InitList(int *list)
{
int i = 0;
count = 0;
for(i = 0; i < KSIZE; i++)
{
list[i] = 0;
}
}
void DestroyList(int *list)
{}
void ClearList(int *list)
{
int i = 0;
count = 0;
for(i = 0; i < KSIZE; i++)
{
list[i] = 0;
}
}
int ListEmpty(int *list)
{
if(count == 0)
{
return TRUE;
}
else
{
return FALSE;
}
}
int ListLength(int *list)
{
return count;
}
int GetElem(int *list, int i, int *e)
{
if(i < count && i >= 0)
{
*e = list[i];
return TRUE;
}
else
{
return FALSE;
}
}
int LocateElem(int *list, int e)
{
int i = 0;
for(i = 0; i < count; i++)
{
if(list[i] == e)
{
return i;
}
}
return -1;
}
/************************************************************************/
/*
-------------------------
| 0 | 1 | 2 | 3 | 4 | |
-------------------------
*/
/************************************************************************/
int ListInsert(int *list, int i, int e)
{
if(i <= count && i >= 0)
{
/*int tempArr[KSIZE] = {0};
int k = 0;
int j = 0;
int m = 0;
for(k = 0; k < i; k++)
{
tempArr[j++] = list[k];
}
tempArr[i] = e;
j++;
for(k = i; k < count ; k++)
{
tempArr[j++] = list[k];
}
count++;
for(m = 0; m < count; m++)
{
list[m] = tempArr[m];
}*/
int k = 0;
for(k = count-1; k >= i; k--)
{
list[k+1] = list[k];
}
list[i] = e;
count++;
return TRUE;
}
else
{
return FALSE;
}
}
int ListDelete(int *list, int i, int *e)
{
if(i < count && i >= 0)
{
int k = 0;
if(e != NULL)
{
*e = list[i];
}
for(k = i; k < count - 1; k++)
{
list[k] = list[k+1];
}
count--;
return TRUE;
}
else
{
return FALSE;
}
}
void ListTraverse(int *list)
{
int i = 0;
for(i = 0; i < count; i++)
{
printf("%d ", list[i]);
}
printf("\n");
}
堆申请内存
#include <stdio.h>
#include <stdlib.h>
#define KSIZE 10
#define FALSE 0
#define TRUE 1
/************************************************************************/
/* 线性表(linear list)
线性表是一个相当灵活的数据结构,它的长度可以根据需要增长和缩短,即对线性表的数据元素不仅可以进行访问,还可以进行插入和删除等。
抽象定义的线性表如下:
ADT:Abstract Data Type 抽象数据类型
ADT LIST
L:LIST简称,即线性表本身
i:索引
e:element简称,即元素
cur_:current简称,即当前元素
pre_:previous简称,即前一个元素
next_:next,即下一个元素
visit:对元素访问的方式
InitList(&L) :初始化线性表
DestroyList(&L) :销毁线性表
ClearList(&L) :清空线性表
ListEmpty(L) :线性表是否为空
ListLength(L) :线性表中元素个数
GetElem(L, i, &e) :获取线性表中指定的元素
LocateElem(L, e, compare()) :给定元素获取第一次出现的索引位置
PriorElem(L, cur_ e, &pre_ e) :给定元素获取其前一个元素
NextElem(L, cur_ e, &next_ e) :给定元素获取其后一个元素
ListInsert(&L, i, e) :将元素插入链表中指定位置
ListDelete(&L, i, &e) :从链表中指定位置删除元素
ListTraverse(L, visit()) :遍历元素
简单线性表--C语言实现
线性表组成类型:int数组*/
/************************************************************************/
/*---------------------------------------
InitList(&L);
DestroyList(&L);
ClearList(&L);
ListEmpty(L);
ListLength(L);
GetElem(L, i, &e);
LocateElem(L, e, compare());
ListInsert(&L, i, e);
ListDelete(&L, i, &e);
ListTraverse(L, visit());
PriorElem(L, cur_ e, &pre_ e);
NextElem(L, cur_ e, &next_ e);
-----------------------------------------*/
int count{};
int size{};//分配的内存空间
void InitList(int *list);
void DestroyList(int *list);
void ClearList(int *list);
int ListEmpty(int *list);
int ListLength(int *list);
int GetElem(int *list, int i, int *e);
int LocateElem(int *list, int e);
int ListInsert(int *list, int i, int e);
int ListDelete(int *list, int i, int *e);
void ListTraverse(int *list);
int main(void)
{
int arr[KSIZE];
int e = 0;
InitList(arr);
ListInsert(arr, 0, 5);
ListInsert(arr, 0, 8);
ListInsert(arr, 1, 7);
ListTraverse(arr);
ListDelete(arr, 0, NULL);
ListTraverse(arr);
GetElem(arr, 1, &e);
printf("e = %d\n", e);
printf("5的索引是%d\n", LocateElem(arr, 5));
ClearList(arr);
if(ListEmpty(arr))
{
printf("线性表为空\n");
}
else
{
printf("线性表不为空\n");
}
printf("线性表的长度为%d\n", ListLength(arr));
DestroyList(arr);
system("pause");
return 0;
}
void InitList(int *list)
{
int i = 0;
count = 0;
size = KSIZE;
//在堆上申请内存
list = reinterpret_cast<int *>(malloc(sizeof (int) * KSIZE));
if (list == nullptr){
return ;
}
for(i = 0; i < KSIZE; i++)
{
list[i] = 0;
}
}
void DestroyList(int *list)
{
free(list);
list = nullptr;
}
void ClearList(int *list)
{
int i = 0;
count = 0;
for(i = 0; i < KSIZE; i++)
{
list[i] = 0;
}
}
int ListEmpty(int *list)
{
if(count == 0)
{
return TRUE;
}
else
{
return FALSE;
}
}
int ListLength(int *list)
{
return count;
}
int GetElem(int *list, int i, int *e)
{
if(i < count && i >= 0)
{
*e = list[i];
return TRUE;
}
else
{
return FALSE;
}
}
int LocateElem(int *list, int e)
{
int i = 0;
for(i = 0; i < count; i++)
{
if(list[i] == e)
{
return i;
}
}
return -1;
}
/************************************************************************/
/*
-------------------------
| 0 | 1 | 2 | 3 | 4 | |
-------------------------
*/
/************************************************************************/
int ListInsert(int *list, int i, int e)
{
if(i <= count && i >= 0)
{
int k = 0;
if (count == size){
size = 2 * count;
list = static_cast<int *>(realloc(list, size));
}
if (list == nullptr){
return FALSE;
}
for(k = count-1; k >= i; k--)
{
list[k+1] = list[k];
}
list[i] = e;
count++;
return TRUE;
}
else
{
return FALSE;
}
}
int ListDelete(int *list, int i, int *e)
{
if(i < count && i >= 0)
{
int k = 0;
if(e != NULL)
{
*e = list[i];
}
for(k = i; k < count - 1; k++)
{
list[k] = list[k+1];
}
count--;
return TRUE;
}
else
{
return FALSE;
}
}
void ListTraverse(int *list)
{
int i = 0;
for(i = 0; i < count; i++)
{
printf("%d ", list[i]);
}
printf("\n");
}
单链表
代码
#include <stdio.h>
#include <stdlib.h>
/************************************************************************/
/* 要求:
定义一个结构体Node,结构体由两个整数组成,
第一个是val,第二个是next
定义一个Node类型的数组,数组有3个Node节点,
3个Node节点的关系如下:
nodeA(5, 2) nodeB(7, -1) nodeC(8, 1)
数组首元素nodeA为头结点,
编写函数ListTraverse遍历此链表
*/
/************************************************************************/
typedef struct tagNode
{
int val;
int next;
}Node;
void ListTraverse(Node *pList);
int main(void)
{
Node list[3] = {
{5,2},
{7,-1},
{8,1}
};
ListTraverse(list);
system("pause");
return 0;
}
void ListTraverse(Node *pList)
{
int i = 0;
Node *pCurrentNode = &pList[i];
while(pCurrentNode->next != -1)
{
printf("%d ", pCurrentNode->val);
i = pCurrentNode->next;
pCurrentNode = &pList[i];
}
printf("%d \n", pCurrentNode->val);
}
链表
/************************************************************************/
/* by 袁春旭 */
/************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/************************************************************************/
/* 要求:
编写一个单链表,每个节点就是一条信息,每条信息包含的内容如下:
姓名:name
联系方式:phone
要求编写的函数如下:
InitList(Node *pHead) :初始化单链表*
DestroyList(Node *pHead) :销毁单链表*
ClearList(Node *pHead) :清空单链表
ListEmpty(Node *pHead) :判断单链表是否为空
ListLength(Node *pHead) :获取单链表中节点个数
GetElem(Node *pHead, int index, Node *pElem) :获取单链表中指定的节点
LocateElem(Node *pHead, Node *pElem) :给定节点获取单链表中第一次出现的索引位置
ListInsert(Node *pHead, int index, Node *pElem) :将节点插入单链表中指定位置*
ListDelete(Node *pHead, int index, Node *pElem) :从单链表中指定位置删除节点*
ListTraverse(Node *pHead) :遍历单链表中所有节点*
作业:
PriorElem(Node *pHead, Node *pCurElem, Node *pPreElem) :获取给定节点的前一个节点
NextElem(Node *pHead, Node *pCurElem, Node *pNextElem) :获取给定节点的后一个节点
打造自己的通讯录
1. 设计通讯录菜单(如:插入信息,查找信息)
2. 扩展节点信息
3. 回顾文件读写知识
提示:
1. 使用记事本保存信息
2. 编写函数将信息从文件中逐一读出并按条写入链表节点
3. 编写函数将链表各个节点逐一写入文件,达到保存的目的
4. 注意读写函数的调用时机:
在程序运行之初加载文件。
在用户执行退出菜单时保存文件。
*/
/************************************************************************/
#define KLen 30
int g_iCount = 0;
typedef struct tagNode
{
char name[KLen];
char phone[KLen];
struct tagNode *pNext;
}Node;
int InitList(Node **pHead);
void ClearList(Node *pHead);
void DestroyList(Node *pHead);
int ListEmpty(Node *pHead);
int ListLength(Node *pHead);
void ListTraverse(Node *pHead);
int GetElem(Node *pHead, int index, Node *pElem);
int LocateElem(Node *pHead, Node *pElem);
int ListInsert(Node *pHead, int index, Node *pElem);
int ListDelete(Node *pHead, int index, Node *pElem);
int main(void)
{
//单元测试
Node *pList = NULL;
Node node1 = {"Jim", "1234", NULL};
Node node2 = {"Merry", "4321", NULL};
Node node3 = {"James", "3456", NULL};
Node node4;
InitList(&pList);
ListInsert(pList, 0, &node1);
printf("%d \n", ListLength(pList));
ListInsert(pList, 1, &node2);
ListInsert(pList, 1, &node3);
printf("%d \n", ListEmpty(pList));
printf("%d \n", ListLength(pList));
ListTraverse(pList);
ListDelete(pList, 2, NULL);
printf("%d \n", ListLength(pList));
ListTraverse(pList);
DestroyList(pList);
system("pause");
return 0;
}
int InitList(Node **pHead)
{
*pHead = (Node *)malloc(sizeof(Node));
if(*pHead == NULL)
{
return 0;
}
(*pHead)->pNext = NULL;
return 1;
}
void ClearList(Node *pHead)
{
Node *pCurrentNode = NULL;
Node *pNextNode = NULL;
if(pHead->pNext != NULL)
{
pCurrentNode = pHead->pNext;
while(pCurrentNode != NULL)
{
pNextNode = pCurrentNode->pNext;
free(pCurrentNode);
pCurrentNode = pNextNode;
}
}
}
void DestroyList(Node *pHead)
{
ClearList(pHead);
free(pHead);
pHead = NULL;
}
int ListEmpty(Node *pHead)
{
/*if(pHead->pNext == NULL)
{
return 1;
}
else
{
return 0;
}*/
if(g_iCount == 0)
{
return 1;
}
return 0;
}
int ListLength(Node *pHead)
{
//int count = 0;
//Node *pCurrentNode = pHead->pNext;
//while(pCurrentNode != NULL)
//{
// count++;
// //printf("姓名:%s ", pCurrentNode->name);
// //printf("电话:%s ", pCurrentNode->phone);
// pCurrentNode = pCurrentNode->pNext;
//}
//return count;
return g_iCount;
}
void ListTraverse(Node *pHead)
{
Node *pCurrentNode = pHead->pNext;
while(pCurrentNode != NULL)
{
printf("姓名:%s ", pCurrentNode->name);
printf("电话:%s ", pCurrentNode->phone);
printf("\n");
pCurrentNode = pCurrentNode->pNext;
}
printf("\n\n");
}
int GetElem(Node *pHead, int index, Node *pElem)
{
int count = 0;
if(index < 0 || index > g_iCount)
{
return 0;
}
Node *pCurrentNode = pHead;
while(pCurrentNode != NULL)
{
if(count == index)
{
pElem = pCurrentNode;
return 1;
}
count++;
pCurrentNode = pCurrentNode->pNext;
}
return 1;
}
int LocateElem(Node *pHead, Node *pElem)
{
int index = 1;
Node *pCurrentNode = pHead->pNext;
while(pCurrentNode != NULL)
{
if(!strcmp(pCurrentNode->name, pElem->name)&& !strcmp(pCurrentNode->phone, pElem->phone))
{
return index;
}
pCurrentNode = pCurrentNode->pNext;
index++;
}
return -1;
}
int ListInsert(Node *pHead, int index, Node *pElem)
{
int count = 0;
Node *pNode = NULL;
Node *pCurrentNode = NULL;
if(index < 0 || index > g_iCount)
{
return 0;
}
pNode = (Node *)malloc(sizeof(Node));
if(pNode == NULL)
{
return 0;
}
strcpy(pNode->name, pElem->name);
strcpy(pNode->phone, pElem->phone);
pCurrentNode = pHead;
while(pCurrentNode != NULL)
{
if(count == index)
{
//1. 将当前节点的next指针保存
Node *pTemp = pCurrentNode->pNext;
//2. 让当前节点的next指针指向申请的内存
pCurrentNode->pNext = pNode;
//3. 将保存的next指针赋值给新节点的next指针
pNode->pNext = pTemp;
g_iCount++;
return 1;
}
count++;
pCurrentNode = pCurrentNode->pNext;
}
return 1;
}
int ListDelete(Node *pHead, int index, Node *pElem)
{
int count = 0;
Node *pCurrentNode = pHead;
Node *pPreNode = NULL;
if(index <= 0 || index > g_iCount)
{
return 0;
}
while(pCurrentNode != NULL)
{
if(count == index)
{
//1. 使currentNode的上一个节点指向currentNode的下一个节点
pPreNode->pNext = pCurrentNode->pNext;
if(pElem != NULL)
{
//将要删除的节点数据拷贝出来
strcpy(pElem->name, pCurrentNode->name);
strcpy(pElem->phone, pCurrentNode->phone);
}
//2. 删除currentNode指向的节点
free(pCurrentNode);
g_iCount--;
return 1;
}
count++;
pPreNode = pCurrentNode;
pCurrentNode = pCurrentNode->pNext;
}
return 1;
}