数据结构与算法
数据结构与算法是一个学习计算机绕不过去的话题,而我们大学之中多数课程之中都使用伪代码进行讲解,给对我们的学习理解也是一把双刃剑,虽然可以让我们自己通过算法、思路自己写出程序,但也可能“一叶障目”致使我们迟迟不知道具体到程序语言上问题出在哪里
所以我想自己使用不同的程序设计语言编写简单的数据结构和讲解一些经典的算法,在复习和记录的过程之中也和大家一起交流讨论数据结构与算法的一些巧妙的设计和个人见解与跳过的“坑”,各位共勉。
帖子会慢慢更新,当然速度可能不太能保证,也可能在后续的更新之中调整文章结构。
常用数据结构
线性表
线性表简介
定义
线性表是最基本、最简单、也是最常用的一种数据结构。线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。
优点
线性表的逻辑结构简单,便于实现和操作。因此,线性表这种数据结构在实际应用中是广泛采用的一种数据结构。
特征
1.集合中必存在唯一的一个“第一元素”。
2.集合中必存在唯一的一个 “最后元素” 。
3.除最后一个元素之外,均有唯一的后继。
4.除第一个元素之外,均有唯一的前驱。
线性表示例代码
代码(C语言)
链式线性表 Visual Studio 2019
/**
* 数据结构 C语言链式线性表
* @FileName SingleLinkList.c
* @author W.Lionel.Esaka
*/
#include <stdio.h>
#include <stdlib.h>
typedef int DataType;
#define Status int;
#define CORRECT 1;
#define ERROR 0;
#define OVERFLOW -1;
/*单链表的类型定义如下*/
typedef struct node{
DataType data;
struct node* next;
} LinkNode, * LinkList;
/*创建指定长度单链表 尾插法*/
void CreateListTail(LinkList* list, int Number)
{
LinkList node, r;
int i;
srand(time(0));
*list = (LinkList*)malloc(sizeof(LinkList));
r = *list;
for (i = 0; i < Number; i++)
{
node = (LinkNode*)malloc(sizeof(LinkNode));
node->data = rand() % 100 + 1;
r->next = node;
r = node;
}
r->next = NULL;
}
/* 插入元素 */
Status InsertLinkList(LinkList* list, int position, DataType value)
{
int i = 1;
LinkList p, s;
p = *list;
while (p && i < position)
{
p = p->next;
i++;
}
if ( !p || i > position)
{
return ERROR;
}
s = (LinkList)malloc(sizeof(LinkNode));
s->data = value;
s->next = p->next;
p->next = s;
return CORRECT;
}
/*删除元素 */
Status DeleteLinkList(LinkList* list, int position, DataType* value)
{
int i = 1;
LinkList p, q;
p = *list;
while (p->next && i < position)
{
p = p->next;
i++;
}
if (!(p->next) || i > position)
{
return ERROR;
}
q = p->next;
p->next = q->next;
*value = q->data;
free(q);
return CORRECT;
}
/*打印链表数据*/
void DisPlayList(LinkList* list)
{
LinkList p;
p = *list;
int i = 0;
printf("\n链表数据如下:\n");
while (p->next != NULL)
{
p = p->next;
printf("%d,\t", p->data);
i++;
if (i%10 == 0) printf("\n");
}
printf("\n链表长度为%d\n", i);
}
/*
将一个带头结点的单链表 A 分解为两个具有相同结构的链表 B 和C。
其中 B 表中的结点为 A 表中值为奇数的结点,而 C 表中的结点为 A 表中值为偶数的结点。
*/
void func(LinkList* A, LinkList* B, LinkList* C)
{
LinkList p1;
p1 = *A;
while (p1->next != NULL)
{
p1 = p1->next;
if ( odd(p1->data) )
{
InsertLinkList(B, 1, p1->data);
}
else
{
InsertLinkList(C, 1, p1->data);
}
}
}
/*清空链表*/
Status ClearList(LinkList* list)
{
LinkList p, q;
p = (*list)->next;
while (p)
{
q = p->next;
free(p);
p = q;
}
(*list)->next = NULL;
return CORRECT;
}
/*odd(x) 为判奇数函数,x 为奇数,返回 1,否则返回 0。*/
int odd(int x)
{
if (x & 1)
{
return 1;
}
else
{
return 0;
}
}
/*入口 演示main*/
void main()
{
LinkList linklistA, linklistB, linklistC;
LinkList* listA = &linklistA;
LinkList* listB = &linklistB;
LinkList* listC = &linklistC;
int value = 0;
CreateListTail(listA, 20);
printf("单链表LinkListA");
DisPlayList(listA);
printf("\n将一个带头结点的单链表 A 分解为两个具有相同结构的链表 B 和 C \n");
printf("其中 B 表中的结点为 A 表中值为奇数的结点,而 C 表中的结点为 A 表中值为偶数的结点\n");
CreateListTail(listB, 0);
CreateListTail(listC, 0);
func(listA,listB,listC);
printf("单链表LinkListB");
DisPlayList(listB);
printf("\n");
printf("单链表LinkListC");
DisPlayList(listC);
}
单链表实例 学生信息链表
代码(C语言)
学生信息链表 Dev-C++ 5.11
/**
* 数据结构 C语言链式线性表
* @FileName StuInfoSys.c
* @author W.Lionel.Esaka
*/
//头文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
//预处理 布尔变量 宏定义
#define Status int;
#define CORRECT 1;
#define ERROR 0;
#define OVERFLOW -1;
/*定义单链表节点*/
typedef struct Node {
char stunum[10] ;
char name[10] ;
float grade;
struct Node* Next;
} Node;
typedef struct Node* LinkList;
/*
创建指定长度单链表 头插法
根据指定学生个数,逐个输入学生信息
*/
void CreateListHead(LinkList *list,int Number) {
LinkList node;
int i;
*list = (LinkList*)malloc(sizeof(Node));
(*list)->Next = NULL;
printf("请输入%d学生信息\n",Number);
for (i = 0; i < Number; i++) {
node = (LinkList*)malloc(sizeof(Node));
scanf("%s %s %f",&node->stunum,&node->name,&node->grade);
node->Next = (*list)->Next;
(*list)->Next = node;
}
}
/*
创建指定长度单链表 尾插法
根据指定学生个数,逐个输入学生信息
*/
void CreateListTail(LinkList* list, int Number) {
LinkList node,r;
int i;
*list = (LinkList*)malloc(sizeof(LinkList));
r = *list;
for (i = 0; i < Number; i++)
{
node = (Node*)malloc(sizeof(Node));
scanf("%s %s %f",&node->stunum,&node->name,&node->grade);
r->Next = node;
r = node;
}
r->Next = NULL;
}
/*
插入元素
给定一个学生信息,插入到表中指定的位置
*/
Status InsertLinkList(LinkList *list,int position)
{
int i = 1;
LinkList p, s;
p = *list;
printf("请输入要插入到第%d个位置的学生信息\n",position);
while ( p && i < position)
{
p = p->Next;
i++;
}
if ( !p || i > position)
{
return ERROR;
}
s = (LinkList)malloc(sizeof(Node));
scanf("%s %s %f",&s->stunum,&s->name,&s->grade);
s->Next = p->Next;
p->Next = s;
return CORRECT;
}
/*
获取特定位置元素
根据指定的位置可返回相应的学生信息(学号,姓名,成绩)
*/
Status GetValue(LinkList *list, int position)
{
int i = 1;
LinkList p;
p = (*list)->Next;
printf("第%d个位置的学生信息:\n",position);
while ( p!= NULL && i < position ) {
p = p->Next;
i++;
}
if ( !p || i > position)
{
return ERROR;
}
printf("学号:%s\n姓名:%s\n成绩:%f\n",p->stunum,p->name,p->grade);
return CORRECT;
}
/*
删除元素
删除指定位置的学生记录
*/
Status DeleteLinkList(LinkList* list, int position)
{
int i = 1;
LinkList p,q;
p = *list;
while ( p->Next && i < position)
{
p = p->Next;
i++;
}
if ( !(p->Next) || i > position)
{
return ERROR;
}
q = p->Next;
p->Next = q->Next;
free(q);
printf("已删除第%d个位置的学生信息:\n",position);
return CORRECT;
}
/*
搜索元素
根据姓名进行查找,返回此学生的学号和成绩
*/
void SearchNameInList(LinkList *list)
{
LinkList p;
p = *list;
printf("请输入所要查找的学生姓名:\n");
char Searchname[10] ;
scanf("%s",&Searchname);
while (p->Next != NULL)
{
p = p->Next;
if(strcmp(p->name, Searchname) == 0)
printf("学号:%s\n成绩:%f\n",p->stunum,p->grade);
}
}
/*
输出链表数据
逐个显示学生表中所有学生的相关信息
统计表中学生个数
*/
void DisPlayList(LinkList *list)
{
LinkList p;
p = *list;
int i = 0;
while (p->Next != NULL)
{
p = p->Next;
printf("学号:%s\n姓名:%s\n成绩:%f\n",p->stunum,p->name,p->grade);
i++;
}
printf("\n学生总数为%d\n",i);
}
/*入口*/
void main()
{
//创建一个表
LinkList linklist;
LinkList* list = &linklist;
//头插法,创建一个可以包含五个信息的表
CreateListHead(list, 5);
//打印链表
DisPlayList(list);
//在第四个位置插入信息
InsertLinkList(list, 4);
//打印链表
DisPlayList(list);
//获取第三个学生的信息
GetValue(list, 3);
//删除第四个学生的信息
DeleteLinkList(list,4);
//打印链表
DisPlayList(list);
//根据输入的学生姓名 显示其其他信息
SearchNameInList(list);
}
循环链表
循环链表简介
定义
循环链表是另一种形式的链式存储结构。它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环。
特征
循环链表的特点是无须增加存储量,仅对表的链接方式稍作改变,即可使得表处理更加方便灵活。
用尾指针rear表示的单循环链表对开始结点a1和终端结点an查找时间都是O(1)。而表的操作常常是在表的首尾位置上进行,因此,实用中多采用尾指针表示单循环链表。带尾指针的单循环链表。
循环链表示例代码
代码(C语言)
单循环链表 Visual Studio 2019
/**
* 数据结构 C语言单循环链表
* @FileName Circular_Linked_List.c
* @author W.Lionel.Esaka
*/
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define Status int;
#define CORRECT 1;
#define ERROR 0;
#define OVERFLOW -1;
typedef int ElemType;
/*定义循环链表结点*/
typedef struct CLinkedList {
ElemType data;
struct CLinkedList* Next;
}Node;
/*初始化链表*/
void ListInit(Node** p)//如果链表为空,则创建一个链表,指针域指向自己,否则寻找尾节点,将
{
//将尾节点的指针域指向这个新节点,新节点的指针域指向头结点
int item;
Node* temp;
Node* target;
printf("输入节点的值,输入0结束\n");
while (1)
{
scanf("%d", &item);
if (item == 0) return;
if (*p == NULL) //如果输入的链表是空。则创建一个新的节点,使其next指针指向自己 (*head)->next=*head;
{
*p = (Node*)malloc(sizeof(Node));
if (!*p) exit(0);
(*p)->data = item;
(*p)->Next = *p;
}
else //输入的链表不是空的,寻找链表的尾节点,使尾节点的next=新节点。新节点的next指向头节点
{
for (target = *p; target->Next != *p; target = target->Next);