408数据结构代码模板修正版

 

目录

二叉树的结点定义

普通二叉树的链式存储结点定义

线索二叉树的结点定义

先序、中序、后序遍历(递归)

层序遍历

先序遍历(非递归)

中序遍历(非递归)

后序遍历(非递归)

图的存储结构

邻接矩阵的结点定义

邻接表的结点定义

图的遍历方式DFS和BFS

排序算法

折半插入排序

起泡排序

快速排序

归并算法


二叉树的结点定义

普通二叉树的链式存储结点定义

typedef struct BTNode {
  char data;  // 这里默认结点data域为char类型
  struct BTNode *lchild;  // 左儿子
  struct BTNode *rchild;  // 右儿子
}BTNode;

线索二叉树的结点定义

typedef struct TBTNode{
  char data;
  int ltag, rtag;
  struct TBTNode *lchild;
  struct TBTNode *rchild;
}TBTNode;

先序、中序、后序遍历(递归)

//先序遍历
void preorder(BTNode *p) {
  if (p != nullptr) {  // 一定要记得判空
    printf("%c ", p->data);
    preorder(p->lchild);
    preorder(p->rchild);
 }
}

//中序遍历
void inorder(BTNode *p) {
  if (p != nullptr) {
    inorder(p->lchild);
    printf("%c ", p->data);
    inorder(p->rchild);
 }
}

//后序遍历
void postorder(BTNode *p) {
  if (p != nullptr) {
    postorder(p->lchild);
    postorder(p->rchild);
    printf("%c ", p->data);
 }
}

层序遍历

/*
定义变量,判空,根入队
循环,出队,访左右
*/
void level(BTNode *bt) {
  BTNode *que[maxSize];
  BTNode *p = null;
  int front = 0, rear = 0;  // 定义一个循环队列

  if (bt != null) {
    rear = (rear+1) % maxSize;
    que[rear] = bt;  // 让根节点入队

    while (front != rear) {  // 只要队列不空,则进行循环
      front = (front+1) % maxSize;
      p = que[front];  // 队头元素出队

      printf("%c\n", p->data);  // 访问队头元素
      if (p->lchild) {  // 左子树存在,则左子树根节点入队
        rear = (rear+1) % maxSize;
        que[rear] = p->lchild;
     }
      if (p->rchild) {  // 右子树存在,则右子树根节点入队
        rear = (rear+1) % maxSize;
        que[rear] = p->rchild;
     }
   }
 }

先序遍历(非递归)

/*
定义变量,判空,根入栈
循环,出栈,访右左
*/
void preorderN(BTNode *bt) {
    BTNode *Stack[maxSize];
    BTNode *p;
    int top = -1;  // 定义人工栈
        
    if (bt != null) {
        Stack[++top] = bt;  // 根节点入栈

        while (top != -1) {  // 判断不空
          p = Stack[top--];  // 出栈 并完成一次访问
          printf("%c\n", p->data);
          if (p->rchild != null)   // 记得,先序遍历一定是先右孩子,再左孩子
            Stack[++top] = p->rchild;
          if (p->lchild != null) 
            Stack[++top] = p->lchild;
       }
     }
}

中序遍历(非递归)

//思想:一直左坠,打印,访右
void inorderN(BTNode *bt) {
  BTNode *Stack[maxSize];
  BTNode *p = bt;
  int top = -1;
  
  if (bt != null) {

    while (top != -1 || p != null) {
      while (p != null) {
        Stack[++top] = p;
        p = p->lchild;
     }

      if (top != -1) {
        p = Stack[top--];
        printf("%c\n", p->data);
        p = p->rchild;
     }
   }
 }
}

后序遍历(非递归)

//思想:栈1访问,栈2存数据,最后一次打印栈2
void postorderN(BTNode *bt) {
  BTNode *Stack1[maxSize]; int top1 = -1;
  BTNode *Stack2[maxSize]; int top2 = -1;  // 定义两个栈
  BTNode *p;
  
  if (bt != nullptr) {
    Stack1[++top1] = bt;

    while (top1 != -1) {
      p = Stack1[top1--];
      Stack2[++top2] = p;  // 注意这里与先序的区别,放入栈2中即可
      if (p->lchild) 
        Stack1[++top1] = p->lchild;
      if (p->rchild) 
        Stack1[++top1] = p->rchild;
   }
    // 这时候循环结束,则会将逆后序遍历的结果都存放到了栈2中
    // 所以对栈2进行输出即可得到后序遍历的结果
    while (top2 != -1) {
      p = Stack2[top2--];
      printf("%c\n", p->data);
   }
 }
}

图的存储结构

邻接矩阵的结点定义

typedef struct {
  int no;  // 顶点编号
  char info;  // 顶点的其他信息,这里默认为char型。
}VertexType;  // 顶点类型

typedef struct {
  int edges[maxSize][maxSize];  // 有权图则将int改为float
  int n, e;  // 分别为定点数和边数
  VertexType vex[maxSize];  // 存放节点信息
}MGraph;  // 图的邻接矩阵类型

邻接表的结点定义

typedef struct ArcNode{
  int adjvex;  // 该边所指向的节点的位置
  struct ArcNode *nextarc;  // 指向下一条边的指针
  int info;  // 该边的相关信息(如权值)
}ArcNode;

typedef struct {
  char data;  // 定点信息
  ArcNode *firstarc;  // 指向第一条边的指针
}VNode;

typedef struct{
  VNode adjlist[maxSize];  // 邻接表
  int n, e;  // 定点数和边数
}AGraph;  // 图的邻接表类型

图的遍历方式DFS和BFS(修正)

void DFS(AGraph *G, int v){      //修正
  ArcNode *p;
  visit[v] = 1;
  cout << v << endl;
  p = G->adjlist[v].firstarc;  // 让p指向顶点v的第一条边

  while (p != null) {                        
    if (visit[p->adjvex] == 0)  DFS(G, p->adjvex);
    p = p->nextarc;
 }
}

void BFS(AGraph *G, int v){
  ArcNode *p;
  int que[maxSize]
  int front = 0, rear = 0;  // 定义一个队列
  int j;
  
  visit[v] = 1;
  cout << v << endl;
  rear = (rear+1)%maxSize;  // 入队
  que[rear] = v;

  while (front != rear){
    front = (front+1)%maxSize;  // 顶点出队
    j = que[front];
    p = G->adjlist[j].firstarc;  // p指向出队顶点j的第一条边

    while (p != null) {  // 将p的所有邻接点未被访问的入队
      if (visit[p->adjvex] == 0) {
        rear = (rear+1)%maxSize;
        que[rear] = p->adjvex;
     }
        p = p->nextarc;
   }
 }
}

排序算法

折半插入排序

void BInsertSort(int A[],int n) {
  int i,j,temp;
  int low,mid,high;

  for(i=1; i<n; i++) {
    low=0;
    high=i-1;
    temp=A[i];
    while(low <= high) {   // 下面的折半是为了在i元素的前面查找到合适的插入位置
      mid=(low+high)/2;
      if(A[mid]>temp) high=mid-1;
      else low=mid+1;
   }
    for(j=i-1;j>high;j--) A[j+1]=A[j];      //注意这里的下界,需要考虑两种情况
    A[j+1]=temp; 

 }
}

起泡排序

void BubbleSort(int arr[], int n) {
  int temp;
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n-i-1; ++j) {
      if (arr[j] > arr[j+1]) {
        temp = arr[j];
        arr[j] = arr[j+1];
        arr[j+1] = temp;
     }
   }
 }
}

快速排序

void _quickSort(int nums[], int l, int r) {
  if (l >= r) return;
  
  int pivot = nums[l];
  int low = l+1, high = r;

  while(low <= high) {
    if(nums[low] > pivot && nums[high] < pivot) 
      swap(nums[low++], nums[high--]);
    if(low <= high && nums[low] <= pivot) ++low;  // 一定要带等号
    if(low <= high && nums[high] >= pivot) --high;
  }

  swap(nums[l], nums[high]);
  int p = high;

  _quickSort(nums, l, p-1);
  _quickSort(nums, p+1, r);
}

归并算法

void _merge(int A[], int l, int mid, int r) {
    int temp[r-l+1];
    int i = l, j = mid + 1;
    int m = mid, n = r; 
    int k = 0; 

    while (i <= m && j <= n) {
      if (A[i] <= A[j]) temp[k++] = A[i++];
      else  temp[k++] = A[j++];
    }

    while (i <= m)  temp[k++] = A[i++];
    while (j <= n)  temp[k++] = A[j++];
    for (i = 0; i < k; i++)  A[l+i] = temp[i];
}

void _mergeSort(A arr[], int l, int r) {
  if (l >= r) return;
  int mid = l + (r-l)/2;

  _mergeSort(arr, l, mid);
  _mergeSort(arr, mid+1, r);
  _merge(arr, l, mid, r);
}

其他细节总结

合并两个顺序表

bool merge(SeqList A,SeqList B,SeqList C){
    if(A.length + B.length > C.length)    return false;
    int i=0,j=0,k=0;

    while(i<A.length && j<B.length){
        if(A.data[i]<=B.data[j])    C.data[k++]=A.data[i];
        else    C.data[k++]=B.data[j++];
    }
    
    while(i<A.length)   C.data[k++]=A.data[i++];
    while(j<B.length)   C.data[k++]=B.data[j++];
    C.length = k;
    return true;
}

判断链表是否有环(快慢指针的思想)

typedef struct ListNode {
    int val;
    struct ListNode *next;
 };

bool hasCycle(ListNode *head) {
    ListNode* slow = head;
    ListNode* fast = head;
    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;

        if(slow == fast)
            return true;
    }
    return false;
}

逆转数组

void Reverse(int A[],int l,int r){
    int i,temp;
    for(i=0; i<(r-l+1)/2;i++)
        swap(A[l+i],A[r-i]);
}

void Converse(int A,int n,int p){
    Reverse(A,0,p-1);
    Reverse(A,p,n-1);
    Reverse(A,0,n-1);
}

申请数组等

int*q=(int*)malloc(sizeof(int)*(n+1));  
//对p的访问是,p[2]或*(p+2)
//释放p:free(p);  使用完记得释放

char *pStr =(char*)malloc(sizeof(char)*n);

//全局变量用静态
static  int sum=0;

//memset是按字节赋值的,对int数组只能赋值0和-1
memset(a,0,sizeof(a));
memset(a,-1,sizeof(a));

二分查找

void BSearch(int A[],int n,int x){
    int low=0,high=n-1,mid;
    while(low<=high){
        mid=(low+high)/2;
        if(A[mid]==x)   break;
        else if(A[mid]<x)   low=mid+1;
        else    high=mid-1;
    }
    
    if(low>high){
        for(int j=n-1;j>high;j--)  A[j+1]=A[j];
        A[j+1]=x;
    }
}

猜你喜欢

转载自blog.csdn.net/CJ_035/article/details/109331630